-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(protocol): add ERC20Airdrop test and deployment script (#15752)
Co-authored-by: Keszey Dániel <keszeyd@MacBook-Pro.local>
- Loading branch information
Showing
3 changed files
with
272 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
// SPDX-License-Identifier: MIT | ||
// _____ _ _ _ _ | ||
// |_ _|_ _(_) |_____ | | __ _| |__ ___ | ||
// | |/ _` | | / / _ \ | |__/ _` | '_ (_-< | ||
// |_|\__,_|_|_\_\___/ |____\__,_|_.__/__/ | ||
// | ||
// Email: security@taiko.xyz | ||
// Website: https://taiko.xyz | ||
// GitHub: https://github.com/taikoxyz | ||
// Discord: https://discord.gg/taikoxyz | ||
// Twitter: https://twitter.com/taikoxyz | ||
// Blog: https://mirror.xyz/labs.taiko.eth | ||
// Youtube: https://www.youtube.com/@taikoxyz | ||
|
||
pragma solidity 0.8.24; | ||
|
||
import "../test/DeployCapability.sol"; | ||
import "forge-std/console2.sol"; | ||
|
||
import "../contracts/team/airdrop/ERC20Airdrop.sol"; | ||
|
||
// @KorbinianK , @2manslkh | ||
// As written also in the tests the workflow shall be the following (checklist): | ||
// 1. Is Vault - which will store the tokens - deployed ? | ||
// 2. Is (bridged) TKO token existing ? | ||
// 3. Is ERC20Airdrop contract is 'approved operator' on the TKO token ? | ||
// 4. Proof (merkle root) and minting window related variabes (start, end) set ? | ||
// If YES the answer to all above, we can go live with airdrop, which is like: | ||
// 1. User go to website. -> For sake of simplicity he is eligible | ||
// 2. User wants to mint, but first site established the delegateHash (user sets a delegatee) which | ||
// the user signs | ||
// 3. Backend retrieves the proof and together with signature in the input params, user fires away | ||
// the claimAndDelegate() transaction. | ||
contract DeployERC20Airdrop is DeployCapability { | ||
uint256 public deployerPrivKey = vm.envUint("PRIVATE_KEY"); // Owner of the ERC20 airdrop | ||
// contract | ||
address public bridgedTko = vm.envAddress("BRIDGED_TKO_ADDRESS"); | ||
address public vaultAddress = vm.envAddress("VAULT_ADDRESS"); | ||
|
||
function setUp() external { } | ||
|
||
function run() external { | ||
require(deployerPrivKey != 0, "invalid deployer priv key"); | ||
require(vaultAddress != address(0), "invalid vault address"); | ||
require(bridgedTko != address(0), "invalid bridged tko address"); | ||
|
||
vm.startBroadcast(deployerPrivKey); | ||
|
||
ERC20Airdrop( | ||
deployProxy({ | ||
name: "ERC20Airdrop", | ||
impl: address(new ERC20Airdrop()), | ||
data: abi.encodeCall(ERC20Airdrop.init, (0, 0, bytes32(0), bridgedTko, vaultAddress)) | ||
}) | ||
); | ||
|
||
/// @dev Once the Vault is done, we need to have a contract in that vault through which we | ||
/// authorize the airdrop contract to be a spender of the vault. | ||
// example: | ||
// | ||
// SOME_VAULT_CONTRACT(vaultAddress).approveAirdropContractAsSpender( | ||
// bridgedTko, address(ERC20Airdrop), 50_000_000_000e18 | ||
// ); | ||
|
||
vm.stopBroadcast(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 67 additions & 0 deletions
67
packages/protocol/test/team/airdrop/LibDelegationSigUtil.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.24; | ||
|
||
/// @notice Creating the TypedDataV4 hash | ||
// NOTE: This contract implements the version of the encoding known as "v4", as implemented by the | ||
// JSON RPC method | ||
// https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. | ||
/// @dev IMPORTANT!! This is for testing, but we need this in the UI for recreating the same hash | ||
/// (to be signed by the user). | ||
// A good resource on how-to: | ||
// link: | ||
// https://medium.com/@javaidea/how-to-sign-and-verify-eip-712-signatures-with-solidity-and-typescript-part-1-5118fdda1fe7 | ||
|
||
library LibDelegationSigUtil { | ||
// EIP712 TYPES_HASH. | ||
bytes32 private constant _TYPE_HASH = keccak256( | ||
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" | ||
); | ||
|
||
// For delegation - this TYPES_HASH is fixed. | ||
bytes32 private constant _DELEGATION_TYPEHASH = | ||
keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); | ||
|
||
function getDomainSeparator(address verifierContract) public view returns (bytes32) { | ||
// This is how we create a contract level domain separator! | ||
// todo (@KorbinianK , @2manslkh): Do it off-chain, in the UI | ||
return keccak256( | ||
abi.encode( | ||
_TYPE_HASH, | ||
keccak256(bytes("Taiko Token")), | ||
keccak256(bytes("1")), | ||
block.chainid, | ||
verifierContract | ||
) | ||
); | ||
} | ||
|
||
struct Delegate { | ||
address delegatee; | ||
uint256 nonce; | ||
uint256 expiry; | ||
} | ||
|
||
// computes the hash of a delegation | ||
function getStructHash(Delegate memory _delegate) internal pure returns (bytes32) { | ||
return keccak256( | ||
abi.encode(_DELEGATION_TYPEHASH, _delegate.delegatee, _delegate.nonce, _delegate.expiry) | ||
); | ||
} | ||
|
||
// computes the hash of the fully encoded EIP-712 message for the domain, which can be used to | ||
// recover the signer | ||
function getTypedDataHash( | ||
Delegate memory _permit, | ||
address verifierContract | ||
) | ||
public | ||
view | ||
returns (bytes32) | ||
{ | ||
return keccak256( | ||
abi.encodePacked( | ||
"\x19\x01", getDomainSeparator(verifierContract), getStructHash(_permit) | ||
) | ||
); | ||
} | ||
} |