Skip to content

Commit d00a10c

Browse files
update smart contracts
1 parent 2a42a5e commit d00a10c

2 files changed

Lines changed: 42 additions & 4 deletions

File tree

docs/smart-contracts/deploy-a-contract.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,13 @@ After defining your contract's typed DTOs (as covered in [Contract Interaction](
2525
dotnet add package Nethereum.Web3
2626
```
2727

28+
You need a funded account to deploy — deployment is a transaction that costs gas.
29+
2830
## Using a Code-Generated Deployment Class
2931

30-
The recommended approach is to use Nethereum's code generator to create typed deployment classes from your Solidity ABI and bytecode:
32+
The recommended approach is to use Nethereum's [code generator](./code-generation.md) to create typed deployment classes from your Solidity ABI and bytecode. The generated class inherits from `ContractDeploymentMessage` and contains the bytecode and constructor parameters as properties.
33+
34+
Once you have the deployment class, create a `Web3` instance with your account, populate the constructor parameters, and send:
3135

3236
```csharp
3337
using Nethereum.Web3;
@@ -50,25 +54,37 @@ string contractAddress = transactionReceipt.ContractAddress;
5054
Console.WriteLine($"Contract deployed at: {contractAddress}");
5155
```
5256

57+
The handler encodes your constructor parameters into the deployment bytecode, estimates gas (unless you set it explicitly), manages the nonce, and waits for the transaction to be mined. The `ContractAddress` on the receipt is the address of your new contract.
58+
5359
## Estimating Deployment Gas
5460

61+
If you want to check the gas cost before committing to the deployment, call `EstimateGasAsync` first. This simulates the deployment against the current chain state without actually sending a transaction:
62+
5563
```csharp
5664
var estimatedGas = await deploymentHandler.EstimateGasAsync(deploymentMessage);
5765
Console.WriteLine($"Estimated gas: {estimatedGas.Value}");
5866
deploymentMessage.Gas = estimatedGas;
5967
```
6068

69+
Note that `SendRequestAndWaitForReceiptAsync` estimates gas automatically if you don't set `Gas` on the message — so this step is only needed when you want to display the cost to a user or set a specific gas limit.
70+
6171
## Deploy Without Code-Generated Classes
6272

73+
When prototyping or working with a raw ABI string, you can deploy without a typed class. Pass the ABI, bytecode, sender address, gas limit, and constructor arguments directly:
74+
6375
```csharp
6476
var receipt = await web3.Eth.DeployContract.SendRequestAndWaitForReceiptAsync(
6577
abi, bytecode, account.Address,
6678
new Nethereum.Hex.HexTypes.HexBigInteger(3000000),
6779
null, null, Web3.Convert.ToWei(1000000));
6880
```
6981

82+
This approach is less safe — constructor argument types aren't checked at compile time, so a mismatch will fail at runtime. Use the typed approach for production code.
83+
7084
## Deploying with Multiple Constructor Parameters
7185

86+
Contracts often take multiple constructor arguments. Each parameter maps to a property on the deployment message class:
87+
7288
```csharp
7389
var deployment = new MyNFTDeployment
7490
{
@@ -81,8 +97,12 @@ var handler = web3.Eth.GetContractDeploymentHandler<MyNFTDeployment>();
8197
var receipt = await handler.SendRequestAndWaitForReceiptAsync(deployment);
8298
```
8399

100+
The `[Parameter]` attributes on the deployment class (defined in [Contract Interaction](./guide-smart-contract-interaction)) control how each property maps to the Solidity constructor signature.
101+
84102
## Checking Deployment Status
85103

104+
The receipt's `Status` field tells you whether the deployment succeeded. A status of `1` means success; `0` means the transaction was mined but the contract creation reverted (often due to a `require` failing in the constructor):
105+
86106
```csharp
87107
if (receipt.Status.Value == 1)
88108
{

docs/smart-contracts/erc20.md

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ var receipt = await erc20.TransferRequestAndWaitForReceiptAsync(recipient, amoun
1616
No ABI, no code generation — built-in typed service for any ERC-20 token.
1717
:::
1818

19-
Nethereum has built-in typed services for ERC-20 tokens. No ABI needed, no code generation — just call the methods directly. This is the fastest way to interact with any ERC-20 token and covers the vast majority of use cases.
19+
Nethereum has built-in typed services for ERC-20 tokens. No ABI needed, no code generation — just call the methods directly. This is the fastest way to interact with any ERC-20 token and covers the vast majority of use cases. For the full list of built-in services (ERC-721, ERC-1155, ENS, and more), see [Built-in Standards](./guide-built-in-standards.md).
2020

2121
## Query Token Info
2222

23+
Every ERC-20 token exposes metadata — the name, symbol, decimals, and total supply. These are read-only calls (no gas, no signing needed):
24+
2325
```csharp
2426
var erc20 = web3.Eth.ERC20.GetContractService(contractAddress);
2527

@@ -33,15 +35,21 @@ Console.WriteLine($"Decimals: {decimals}");
3335
Console.WriteLine($"Total supply: {Web3.Convert.FromWei(totalSupply, decimals)}");
3436
```
3537

38+
The `decimals` value is important — ERC-20 tokens store balances as integers in the smallest unit (like Wei for ETH). Most tokens use 18 decimals, but stablecoins like USDC use 6. Always use `Web3.Convert.FromWei(value, decimals)` to display human-readable amounts.
39+
3640
## Check Balance
3741

42+
Balances are returned in the token's smallest unit. Use `FromWei` with the token's decimals to get a readable value:
43+
3844
```csharp
3945
var balance = await erc20.BalanceOfQueryAsync(myAddress);
4046
Console.WriteLine($"Balance: {Web3.Convert.FromWei(balance, decimals)} {symbol}");
4147
```
4248

4349
## Transfer Tokens
4450

51+
To transfer tokens, you need a `Web3` instance connected with a funded account (as shown in the [Contract Interaction guide](./guide-smart-contract-interaction.md)). The amount must be in the smallest unit — use `ToWei` with the token's decimals:
52+
4553
```csharp
4654
var receipt = await erc20.TransferRequestAndWaitForReceiptAsync(
4755
recipientAddress,
@@ -50,9 +58,11 @@ var receipt = await erc20.TransferRequestAndWaitForReceiptAsync(
5058
Console.WriteLine($"Transfer TX: {receipt.TransactionHash}");
5159
```
5260

61+
Gas estimation, nonce management, and EIP-1559 fees are handled automatically.
62+
5363
## Approve and TransferFrom
5464

55-
The approve/transferFrom pattern allows another address (like a DEX) to spend your tokens:
65+
The approve/transferFrom pattern allows another address (like a DEX or smart contract) to spend your tokens. This is a two-step process: first you approve a spending limit, then the spender calls `transferFrom`.
5666

5767
```csharp
5868
// Approve the spender to use 1000 tokens
@@ -65,8 +75,12 @@ var allowance = await erc20.AllowanceQueryAsync(myAddress, spenderAddress);
6575
Console.WriteLine($"Allowance: {Web3.Convert.FromWei(allowance, decimals)}");
6676
```
6777

78+
Be careful with approvals — approving a large amount gives the spender permission to transfer up to that amount at any time. Many DApps request unlimited approval (`BigInteger.MaxValue`) for convenience, but it's safer to approve only what's needed.
79+
6880
## Listen for Transfer Events
6981

82+
ERC-20 transfers emit a `Transfer` event. You can query historical transfers or monitor for new ones. Nethereum ships a built-in `TransferEventDTO` for ERC-20, so you don't need to define your own:
83+
7084
```csharp
7185
var transferEvent = web3.Eth.GetEvent<TransferEventDTO>(contractAddress);
7286
var filter = transferEvent.CreateFilterInput(
@@ -80,16 +94,20 @@ foreach (var t in transfers)
8094
}
8195
```
8296

97+
For more advanced filtering (by sender, recipient, block range), see the [Events guide](./guide-events.md).
98+
8399
## Historical Queries
84100

85-
All query methods accept an optional `BlockParameter` for historical state:
101+
All query methods accept an optional `BlockParameter` to read state at a specific block. This is useful for checking what a balance was at a past point in time:
86102

87103
```csharp
88104
var historicalBalance = await erc20.BalanceOfQueryAsync(
89105
myAddress,
90106
new BlockParameter(15_000_000));
91107
```
92108

109+
The node must have archive state for this block — most public RPC providers only keep recent state. Use an archive node for deep historical queries.
110+
93111
## Next Steps
94112

95113
- [Code Generation](./code-generation.md) -- generate typed services for custom contracts beyond ERC-20

0 commit comments

Comments
 (0)