mirror of
https://github.com/logos-messaging/logos-messaging-rlnv2-contract.git
synced 2026-01-02 14:03:07 +00:00
Initialise TST MaxSupply on deployment (#37)
* Implement init maxSupply when deploying TST * README and comments updates * Move the maxSupply!=zero check to init function and add test * Fix mintWithEth command in test/README.md * Remove incorrect proxy deployment in TestStableTokenFactory * Remove redundant post deploy check * Update test/README with default token amount in ETH * Update README section on Proxy address upgrade * Add example env for TST commands * Add prerequisites section to test/README
This commit is contained in:
parent
c3ec4be6b4
commit
a1d97fcad9
@ -11,13 +11,16 @@ contract DeployTokenWithProxy is BaseScript {
|
||||
}
|
||||
|
||||
function deploy() public returns (ERC1967Proxy) {
|
||||
// Read desired max supply from env or use default
|
||||
uint256 defaultMaxSupply = vm.envOr({ name: "MAX_SUPPLY", defaultValue: uint256(1_000_000 * 10 ** 18) });
|
||||
|
||||
// Deploy the initial implementation
|
||||
address implementation = address(new TestStableToken());
|
||||
|
||||
// Encode the initialize call
|
||||
bytes memory data = abi.encodeCall(TestStableToken.initialize, (1_000_000 * 10 ** 18));
|
||||
// Encode the initialize call (maxSupply)
|
||||
bytes memory initData = abi.encodeCall(TestStableToken.initialize, (defaultMaxSupply));
|
||||
|
||||
// Deploy the proxy with initialization data
|
||||
return new ERC1967Proxy(implementation, data);
|
||||
return new ERC1967Proxy(implementation, initData);
|
||||
}
|
||||
}
|
||||
|
||||
28
test/.env.example.tst
Normal file
28
test/.env.example.tst
Normal file
@ -0,0 +1,28 @@
|
||||
# Example environment variables for TestStableToken commands in test/README.md
|
||||
# Either provide a private key (`DEPLOYER_ACCOUNT_PRIVATE_KEY`) or a mnemonic (`TWELVE_WORD_MNEMONIC`).
|
||||
|
||||
# Deployer account (used as --from / ETH_FROM)
|
||||
DEPLOYER_ACCOUNT_ADDRESS=0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
# Hex private key (prefixed with 0x) OR leave empty if you prefer to use mnemonic
|
||||
DEPLOYER_ACCOUNT_PRIVATE_KEY=0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
|
||||
# Alternatively, use a mnemonic instead of a private key
|
||||
TWELVE_WORD_MNEMONIC="test test test test test test test test test test test junk"
|
||||
|
||||
# RPC URL for accessing testnet via HTTP.
|
||||
# e.g. https://linea-sepolia.infura.io/v3/123aa110320f4aec179150fba1e1b1b1
|
||||
RPC_URL=https://linea-sepolia.infura.io/v3/<key>
|
||||
|
||||
# Optional: override the default max supply (value is in wei; example below = 1_000_000 * 10**18)
|
||||
# Uncomment and set to change the token cap used during initialize/upgrade
|
||||
# MAX_SUPPLY=1000000000000000000000000
|
||||
|
||||
# Addresses used by various actions (leave commented if not applicable)
|
||||
# Proxy contract (when calling upgrade, approve, mint, etc.)
|
||||
# TOKEN_PROXY_ADDRESS=0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
|
||||
# Example account to add to the minter allowlist
|
||||
# ACCOUNT_ADDRESS=0xcccccccccccccccccccccccccccccccccccccccc
|
||||
|
||||
# Private key for a minter account (used when sending mint transactions)
|
||||
# MINTER_ACCOUNT_PRIVATE_KEY=0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
@ -19,12 +19,19 @@ token distribution while mimicking DAI's behaviour.
|
||||
- **Proxy architecture**: Use a proxy contract to minimize updates required when the token address changes across other
|
||||
components (e.g., nwaku-compose repo or dogfooding instructions)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Foundry](https://getfoundry.sh/) installed
|
||||
- An Ethereum account with testnet ETH for deploying contracts and sending transactions
|
||||
|
||||
## Usage
|
||||
|
||||
Add environment variable `MAX_SUPPLY` to set the maximum supply of the token, otherwise it defaults to 1 million tokens.
|
||||
|
||||
### Deploy new TestStableToken with proxy contract
|
||||
|
||||
This script deploys both the proxy and the TestStableToken implementation, initializing the proxy to point to the new
|
||||
implementation.
|
||||
This script deploys both the proxy contract and the TestStableToken implementation contract, initializing the proxy to
|
||||
point to the new implementation.
|
||||
|
||||
```bash
|
||||
ETH_FROM=$DEPLOYER_ACCOUNT_ADDRESS forge script script/DeployTokenWithProxy.s.sol:DeployTokenWithProxy --rpc-url $RPC_URL --broadcast --private_key $DEPLOYER_ACCOUNT_PRIVATE_KEY
|
||||
@ -36,22 +43,43 @@ or
|
||||
MNEMONIC=$TWELVE_WORD_MNEMONIC forge script script/DeployTokenWithProxy.s.sol:DeployTokenWithProxy --rpc-url $RPC_URL --broadcast
|
||||
```
|
||||
|
||||
### Deploy only TestStableToken contract implementation
|
||||
### Deploy only TestStableToken implementation contract
|
||||
|
||||
This script deploys only the TestStableToken implementation, which can then be used to update the proxy contract to
|
||||
point to this new implementation.
|
||||
This script deploys only the TestStableToken implementation. See the upgrade instructions:
|
||||
[Upgrade the proxy](#update-the-proxy-contract-to-point-to-the-new-implementation)
|
||||
|
||||
```bash
|
||||
forge script test/TestStableToken.sol:TestStableTokenFactory --tc TestStableTokenFactory --rpc-url $RPC_URL --private-key $DEPLOYER_ACCOUNT_PRIVATE_KEY --broadcast
|
||||
ETH_FROM=$DEPLOYER_ACCOUNT_ADDRESS forge script test/TestStableToken.sol:TestStableTokenFactory --tc TestStableTokenFactory --rpc-url $RPC_URL --private-key $DEPLOYER_ACCOUNT_PRIVATE_KEY --broadcast
|
||||
```
|
||||
|
||||
### Update the proxy contract to point to the new implementation
|
||||
|
||||
#### Option 1: Update proxy implementation address only (recommended when the proxy is already initialized)
|
||||
|
||||
When the proxy is already initialized and the `maxSupply` is set, you can simply update the implementation address using
|
||||
`upgradeTo(address)`.
|
||||
|
||||
```bash
|
||||
# Upgrade the proxy to a new implementation
|
||||
cast send $TOKEN_PROXY_ADDRESS "upgradeTo(address)" $NEW_IMPLEMENTATION_ADDRESS --rpc-url $RPC_URL --private-key $DEPLOYER_ACCOUNT_PRIVATE_KEY
|
||||
```
|
||||
|
||||
#### Option 2: Update proxy implementation address and initialize cap
|
||||
|
||||
When upgrading a UUPS/ERC1967 proxy you should perform the upgrade and initialization in the same transaction to avoid
|
||||
leaving the proxy in an uninitialized state. Use `upgradeToAndCall(address,bytes)` with the initializer calldata.
|
||||
|
||||
```bash
|
||||
# Encode the initializer calldata (example: set MAX_SUPPLY to 1_000_000 ETH = 1_000_000 * 10**18)
|
||||
DATA=$(cast abi-encode "initialize(uint256)" 1000000000000000000000000)
|
||||
|
||||
# Perform upgrade and call initializer atomically
|
||||
cast send $TOKEN_PROXY_ADDRESS "upgradeToAndCall(address,bytes)" $NEW_IMPLEMENTATION_ADDRESS $DATA --rpc-url $RPC_URL --private-key $DEPLOYER_ACCOUNT_PRIVATE_KEY
|
||||
```
|
||||
|
||||
If you must call `upgradeTo` separately (not recommended), follow up immediately with an `initialize(...)` call in the
|
||||
same transaction or as the next transaction from the owner/multisig. However, prefer `upgradeToAndCall` to eliminate the
|
||||
time window where the proxy points to a new implementation but its storage (e.g., `maxSupply`) is uninitialized.
|
||||
|
||||
### Add account to the allowlist to enable minting
|
||||
|
||||
```bash
|
||||
@ -68,8 +96,10 @@ cast send $TOKEN_PROXY_ADDRESS "mint(address,uint256)" <TO_ADDRESS> <AMOUNT> --r
|
||||
|
||||
#### Option 2: Public minting by burning ETH (no privileges required)
|
||||
|
||||
The total tokens minted is determined by the amount of ETH sent with the transaction.
|
||||
|
||||
```bash
|
||||
cast send $TOKEN_PROXY_ADDRESS "mintWithETH(address,uint256)" <TO_ACCOUNT> <AMOUNT> --value <ETH_AMOUNT> --rpc-url $RPC_URL --private-key $MINTING_ACCOUNT_PRIVATE_KEY --from $MINTING_ACCOUNT_ADDRESS
|
||||
cast send $TOKEN_PROXY_ADDRESS "mintWithETH(address)" <TO_ACCOUNT> --value <ETH_AMOUNT> --rpc-url $RPC_URL --private-key $MINTING_ACCOUNT_PRIVATE_KEY --from $MINTING_ACCOUNT_ADDRESS
|
||||
```
|
||||
|
||||
**Note**: The `mintWithETH` function is public and can be called by anyone. It requires sending ETH with the transaction
|
||||
|
||||
@ -8,12 +8,14 @@ import { ERC20PermitUpgradeable } from
|
||||
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
|
||||
import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
|
||||
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
|
||||
import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
|
||||
|
||||
error AccountNotMinter();
|
||||
error AccountAlreadyMinter();
|
||||
error AccountNotInMinterList();
|
||||
error InsufficientETH();
|
||||
error ExceedsMaxSupply();
|
||||
error InvalidMaxSupply(uint256 supplied);
|
||||
|
||||
contract TestStableToken is
|
||||
Initializable,
|
||||
@ -44,6 +46,7 @@ contract TestStableToken is
|
||||
__ERC20Permit_init("TestStableToken");
|
||||
__Ownable_init();
|
||||
__UUPSUpgradeable_init();
|
||||
if (_maxSupply == 0) revert InvalidMaxSupply(_maxSupply);
|
||||
|
||||
maxSupply = _maxSupply;
|
||||
}
|
||||
|
||||
@ -8,7 +8,8 @@ import {
|
||||
AccountAlreadyMinter,
|
||||
AccountNotInMinterList,
|
||||
InsufficientETH,
|
||||
ExceedsMaxSupply
|
||||
ExceedsMaxSupply,
|
||||
InvalidMaxSupply
|
||||
} from "./TestStableToken.sol";
|
||||
import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
|
||||
import { DeployTokenWithProxy } from "../script/DeployTokenWithProxy.s.sol";
|
||||
@ -336,4 +337,18 @@ contract TestStableTokenTest is Test {
|
||||
vm.expectRevert("Ownable: caller is not the owner");
|
||||
token.setMaxSupply(newMaxSupply);
|
||||
}
|
||||
|
||||
function test__InitializeZeroReverts() external {
|
||||
// Deploy implementation directly
|
||||
TestStableToken implementation = new TestStableToken();
|
||||
|
||||
// Build initializer calldata with zero
|
||||
bytes memory initData = abi.encodeCall(TestStableToken.initialize, (uint256(0)));
|
||||
|
||||
// Expect the InvalidMaxSupply reversion including the supplied value
|
||||
vm.expectRevert(abi.encodeWithSelector(InvalidMaxSupply.selector, uint256(0)));
|
||||
|
||||
// Attempt to deploy proxy with initData - should revert
|
||||
new ERC1967Proxy(address(implementation), initData);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user