diff --git a/examples/CRISP/sdk/README.md b/examples/CRISP/sdk/README.md index 289dc9126a..fef4afc62b 100644 --- a/examples/CRISP/sdk/README.md +++ b/examples/CRISP/sdk/README.md @@ -1,6 +1,6 @@ # CRISP SDK -This package is CRISP's TypeScript SDK for interacting with CRISP and the CRISP server. +This package is CRISP's TypeScript SDK for interacting with CRISP and the CRISP server. ## Installation @@ -10,9 +10,9 @@ npm install @enclave/crisp-sdk ## Release -The SDK is published on npmjs and does not follow the same versioning as the main Enclave packages. +The SDK is published on npmjs and does not follow the same versioning as the main Enclave packages. To release a new version, run the following command: -```bash +```bash pnpm release -``` \ No newline at end of file +``` diff --git a/examples/CRISP/sdk/package.json b/examples/CRISP/sdk/package.json index 2412cdf19a..5a068deb39 100644 --- a/examples/CRISP/sdk/package.json +++ b/examples/CRISP/sdk/package.json @@ -36,5 +36,10 @@ "vitest": "^1.6.1", "typescript": "^5.0.0" }, - "packageManager": "pnpm@10.7.1+sha512.2d92c86b7928dc8284f53494fb4201f983da65f0fb4f0d40baafa5cf628fa31dae3e5968f12466f17df7e97310e30f343a648baea1b9b350685dafafffdf5808" + "packageManager": "pnpm@10.7.1+sha512.2d92c86b7928dc8284f53494fb4201f983da65f0fb4f0d40baafa5cf628fa31dae3e5968f12466f17df7e97310e30f343a648baea1b9b350685dafafffdf5808", + "dependencies": { + "@zk-kit/lean-imt": "^2.2.4", + "poseidon-lite": "^0.3.0", + "viem": "2.30.6" + } } diff --git a/examples/CRISP/sdk/src/artifacts/ERC20Votes.json b/examples/CRISP/sdk/src/artifacts/ERC20Votes.json new file mode 100644 index 0000000000..6f4ff6ff0a --- /dev/null +++ b/examples/CRISP/sdk/src/artifacts/ERC20Votes.json @@ -0,0 +1,847 @@ +{ + "abi": [ + { + "type": "function", + "name": "CLOCK_MODE", + "inputs": [], + "outputs": [{ "name": "", "type": "string", "internalType": "string" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "DOMAIN_SEPARATOR", + "inputs": [], + "outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "allowance", + "inputs": [ + { "name": "owner", "type": "address", "internalType": "address" }, + { "name": "spender", "type": "address", "internalType": "address" } + ], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "approve", + "inputs": [ + { "name": "spender", "type": "address", "internalType": "address" }, + { "name": "amount", "type": "uint256", "internalType": "uint256" } + ], + "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "balanceOf", + "inputs": [{ "name": "account", "type": "address", "internalType": "address" }], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "checkpoints", + "inputs": [ + { "name": "account", "type": "address", "internalType": "address" }, + { "name": "pos", "type": "uint32", "internalType": "uint32" } + ], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct ERC20VotesUpgradeable.Checkpoint", + "components": [ + { "name": "fromBlock", "type": "uint32", "internalType": "uint32" }, + { "name": "votes", "type": "uint224", "internalType": "uint224" } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "clock", + "inputs": [], + "outputs": [{ "name": "", "type": "uint48", "internalType": "uint48" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "decimals", + "inputs": [], + "outputs": [{ "name": "", "type": "uint8", "internalType": "uint8" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "decreaseAllowance", + "inputs": [ + { "name": "spender", "type": "address", "internalType": "address" }, + { "name": "subtractedValue", "type": "uint256", "internalType": "uint256" } + ], + "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "delegate", + "inputs": [{ "name": "delegatee", "type": "address", "internalType": "address" }], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "delegateBySig", + "inputs": [ + { "name": "delegatee", "type": "address", "internalType": "address" }, + { "name": "nonce", "type": "uint256", "internalType": "uint256" }, + { "name": "expiry", "type": "uint256", "internalType": "uint256" }, + { "name": "v", "type": "uint8", "internalType": "uint8" }, + { "name": "r", "type": "bytes32", "internalType": "bytes32" }, + { "name": "s", "type": "bytes32", "internalType": "bytes32" } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "delegates", + "inputs": [{ "name": "account", "type": "address", "internalType": "address" }], + "outputs": [{ "name": "", "type": "address", "internalType": "address" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "eip712Domain", + "inputs": [], + "outputs": [ + { "name": "fields", "type": "bytes1", "internalType": "bytes1" }, + { "name": "name", "type": "string", "internalType": "string" }, + { "name": "version", "type": "string", "internalType": "string" }, + { "name": "chainId", "type": "uint256", "internalType": "uint256" }, + { "name": "verifyingContract", "type": "address", "internalType": "address" }, + { "name": "salt", "type": "bytes32", "internalType": "bytes32" }, + { "name": "extensions", "type": "uint256[]", "internalType": "uint256[]" } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getPastTotalSupply", + "inputs": [{ "name": "timepoint", "type": "uint256", "internalType": "uint256" }], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getPastVotes", + "inputs": [ + { "name": "account", "type": "address", "internalType": "address" }, + { "name": "timepoint", "type": "uint256", "internalType": "uint256" } + ], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getVotes", + "inputs": [{ "name": "account", "type": "address", "internalType": "address" }], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "increaseAllowance", + "inputs": [ + { "name": "spender", "type": "address", "internalType": "address" }, + { "name": "addedValue", "type": "uint256", "internalType": "uint256" } + ], + "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [{ "name": "", "type": "string", "internalType": "string" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "nonces", + "inputs": [{ "name": "owner", "type": "address", "internalType": "address" }], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "numCheckpoints", + "inputs": [{ "name": "account", "type": "address", "internalType": "address" }], + "outputs": [{ "name": "", "type": "uint32", "internalType": "uint32" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "permit", + "inputs": [ + { "name": "owner", "type": "address", "internalType": "address" }, + { "name": "spender", "type": "address", "internalType": "address" }, + { "name": "value", "type": "uint256", "internalType": "uint256" }, + { "name": "deadline", "type": "uint256", "internalType": "uint256" }, + { "name": "v", "type": "uint8", "internalType": "uint8" }, + { "name": "r", "type": "bytes32", "internalType": "bytes32" }, + { "name": "s", "type": "bytes32", "internalType": "bytes32" } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "symbol", + "inputs": [], + "outputs": [{ "name": "", "type": "string", "internalType": "string" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "totalSupply", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view" + }, + { + "type": "function", + "name": "transfer", + "inputs": [ + { "name": "to", "type": "address", "internalType": "address" }, + { "name": "amount", "type": "uint256", "internalType": "uint256" } + ], + "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "transferFrom", + "inputs": [ + { "name": "from", "type": "address", "internalType": "address" }, + { "name": "to", "type": "address", "internalType": "address" }, + { "name": "amount", "type": "uint256", "internalType": "uint256" } + ], + "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], + "stateMutability": "nonpayable" + }, + { + "type": "event", + "name": "Approval", + "inputs": [ + { "name": "owner", "type": "address", "indexed": true, "internalType": "address" }, + { "name": "spender", "type": "address", "indexed": true, "internalType": "address" }, + { "name": "value", "type": "uint256", "indexed": false, "internalType": "uint256" } + ], + "anonymous": false + }, + { + "type": "event", + "name": "DelegateChanged", + "inputs": [ + { "name": "delegator", "type": "address", "indexed": true, "internalType": "address" }, + { "name": "fromDelegate", "type": "address", "indexed": true, "internalType": "address" }, + { "name": "toDelegate", "type": "address", "indexed": true, "internalType": "address" } + ], + "anonymous": false + }, + { + "type": "event", + "name": "DelegateVotesChanged", + "inputs": [ + { "name": "delegate", "type": "address", "indexed": true, "internalType": "address" }, + { "name": "previousBalance", "type": "uint256", "indexed": false, "internalType": "uint256" }, + { "name": "newBalance", "type": "uint256", "indexed": false, "internalType": "uint256" } + ], + "anonymous": false + }, + { "type": "event", "name": "EIP712DomainChanged", "inputs": [], "anonymous": false }, + { + "type": "event", + "name": "Initialized", + "inputs": [{ "name": "version", "type": "uint8", "indexed": false, "internalType": "uint8" }], + "anonymous": false + }, + { + "type": "event", + "name": "Transfer", + "inputs": [ + { "name": "from", "type": "address", "indexed": true, "internalType": "address" }, + { "name": "to", "type": "address", "indexed": true, "internalType": "address" }, + { "name": "value", "type": "uint256", "indexed": false, "internalType": "uint256" } + ], + "anonymous": false + } + ], + "bytecode": { "object": "0x", "sourceMap": "", "linkReferences": {} }, + "deployedBytecode": { "object": "0x", "sourceMap": "", "linkReferences": {} }, + "methodIdentifiers": { + "CLOCK_MODE()": "4bf5d7e9", + "DOMAIN_SEPARATOR()": "3644e515", + "allowance(address,address)": "dd62ed3e", + "approve(address,uint256)": "095ea7b3", + "balanceOf(address)": "70a08231", + "checkpoints(address,uint32)": "f1127ed8", + "clock()": "91ddadf4", + "decimals()": "313ce567", + "decreaseAllowance(address,uint256)": "a457c2d7", + "delegate(address)": "5c19a95c", + "delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)": "c3cda520", + "delegates(address)": "587cde1e", + "eip712Domain()": "84b0196e", + "getPastTotalSupply(uint256)": "8e539e8c", + "getPastVotes(address,uint256)": "3a46b1a8", + "getVotes(address)": "9ab24eb0", + "increaseAllowance(address,uint256)": "39509351", + "name()": "06fdde03", + "nonces(address)": "7ecebe00", + "numCheckpoints(address)": "6fcfff45", + "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": "d505accf", + "symbol()": "95d89b41", + "totalSupply()": "18160ddd", + "transfer(address,uint256)": "a9059cbb", + "transferFrom(address,address,uint256)": "23b872dd" + }, + "rawMetadata": "{\"compiler\":{\"version\":\"0.8.29+commit.ab55807c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"EIP712DomainChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"CLOCK_MODE\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DOMAIN_SEPARATOR\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"pos\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"fromBlock\",\"type\":\"uint32\"},{\"internalType\":\"uint224\",\"name\":\"votes\",\"type\":\"uint224\"}],\"internalType\":\"struct ERC20VotesUpgradeable.Checkpoint\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"clock\",\"outputs\":[{\"internalType\":\"uint48\",\"name\":\"\",\"type\":\"uint48\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"eip712Domain\",\"outputs\":[{\"internalType\":\"bytes1\",\"name\":\"fields\",\"type\":\"bytes1\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"verifyingContract\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"salt\",\"type\":\"bytes32\"},{\"internalType\":\"uint256[]\",\"name\":\"extensions\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"timepoint\",\"type\":\"uint256\"}],\"name\":\"getPastTotalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"timepoint\",\"type\":\"uint256\"}],\"name\":\"getPastVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVotes\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"permit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting power can be queried through the public accessors {getVotes} and {getPastVotes}. By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. _Available since v4.2._\",\"events\":{\"Approval(address,address,uint256)\":{\"details\":\"Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance.\"},\"DelegateChanged(address,address,address)\":{\"details\":\"Emitted when an account changes their delegate.\"},\"DelegateVotesChanged(address,uint256,uint256)\":{\"details\":\"Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.\"},\"EIP712DomainChanged()\":{\"details\":\"MAY be emitted to signal that the domain could have changed.\"},\"Initialized(uint8)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"Transfer(address,address,uint256)\":{\"details\":\"Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero.\"}},\"kind\":\"dev\",\"methods\":{\"CLOCK_MODE()\":{\"details\":\"Description of the clock\"},\"DOMAIN_SEPARATOR()\":{\"details\":\"Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\"},\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"checkpoints(address,uint32)\":{\"details\":\"Get the `pos`-th checkpoint for `account`.\"},\"clock()\":{\"details\":\"Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting).\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"delegate(address)\":{\"details\":\"Delegate votes from the sender to `delegatee`.\"},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Delegates votes from signer to `delegatee`\"},\"delegates(address)\":{\"details\":\"Get the address `account` is currently delegating to.\"},\"eip712Domain()\":{\"details\":\"See {EIP-5267}. _Available since v4.9._\"},\"getPastTotalSupply(uint256)\":{\"details\":\"Retrieve the `totalSupply` at the end of `timepoint`. Note, this value is the sum of all balances. It is NOT the sum of all the delegated votes! Requirements: - `timepoint` must be in the past\"},\"getPastVotes(address,uint256)\":{\"details\":\"Retrieve the number of votes for `account` at the end of `timepoint`. Requirements: - `timepoint` must be in the past\"},\"getVotes(address)\":{\"details\":\"Gets the current votes balance for `account`\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"nonces(address)\":{\"details\":\"Returns the current nonce for `owner`. This value must be included whenever a signature is generated for {permit}. Every successful call to {permit} increases ``owner``'s nonce by one. This prevents a signature from being used multiple times.\"},\"numCheckpoints(address)\":{\"details\":\"Get number of checkpoints for `account`.\"},\"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)\":{\"details\":\"Sets `value` as the allowance of `spender` over ``owner``'s tokens, given ``owner``'s signed approval. IMPORTANT: The same issues {IERC20-approve} has related to transaction ordering also apply here. Emits an {Approval} event. Requirements: - `spender` cannot be the zero address. - `deadline` must be a timestamp in the future. - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments. - the signature must use ``owner``'s current nonce (see {nonces}). For more information on the signature format, see the https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section]. CAUTION: See Security Considerations above.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`.\"}},\"stateVariables\":{\"__gap\":{\"details\":\"This empty reserved space is put in place to allow future versions to add new variables without shifting down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/ERC20VotesUpgradeable.sol\":\"ERC20VotesUpgradeable\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@aragon/osx-commons-contracts/=lib/osx-commons/contracts/\",\":@aragon/osx/=lib/osx/packages/contracts/src/\",\":@aragon/token-voting-plugin/=node_modules/@aragon/token-voting-plugin/src/\",\":@enclave-e3/contracts/=node_modules/@enclave-e3/contracts/\",\":@ensdomains/buffer/=lib/buffer/\",\":@ensdomains/ens-contracts/=lib/ens-contracts/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":ds-test/=lib/openzeppelin-contracts-upgradeable/lib/forge-std/lib/ds-test/src/\",\":ens-contracts/=lib/ens-contracts/contracts/\",\":erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/\",\":forge-std/=lib/forge-std/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\",\":openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":osx-commons/=lib/osx-commons/\",\":osx/=lib/osx/\"]},\"sources\":{\"lib/openzeppelin-contracts-upgradeable/contracts/governance/utils/IVotesUpgradeable.sol\":{\"keccak256\":\"0x2d600bbef9320309cd2a86c1d087eb9d6dbcc00430713ee54bbc5c5a2a11ba31\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://52a5380b861d676adef15f33f8f643e236a1acb2d9456beb4065307eaa22bc2a\",\"dweb:/ipfs/QmdwSfxrafQubVvCoQCU5T7bbPR8JDWU1WotSDXSiUdm33\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/interfaces/IERC5267Upgradeable.sol\":{\"keccak256\":\"0xe562dab443278837fa50faddb76743399e942181881db8dccaea3bd1712994db\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://79ebe0e661396045cefe94f4256398cf632756d779a6871319db374c9eb128c9\",\"dweb:/ipfs/QmfCTCivb9fFhyCX8hzushzcKunvKL2N9RDsnRNdvbd11M\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/interfaces/IERC5805Upgradeable.sol\":{\"keccak256\":\"0x19848eec9045c8b91f1ab6b1853966443e3e36bcbc307593ed37a9f0df179d69\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a07972c1330ee99a5d051b393260e01412ac4c14c7bc4d75d80b7cce291a6412\",\"dweb:/ipfs/QmQx1ZiAo4AbSobN41c1xUEtyX1QejydWCmY7Sj3H5aDNv\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/interfaces/IERC6372Upgradeable.sol\":{\"keccak256\":\"0x3026befd6d69d1b46960bdc35a2ad37c0e1352f26983ee3728dd61fd32aa308a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c2001b7209fd4920ec7674f194db7fe163dfea7a7af2dd25fe6c0e5a94dc595c\",\"dweb:/ipfs/QmXX2zTFyiNWoDxivV3trKcKWifAENMqNAB34NgjWq5feX\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f103ee2e4aecd37aac6ceefe670709cdd7613dee25fa2d4d9feaf7fc0aaa155e\",\"dweb:/ipfs/QmRiNZLoJk5k3HPMYGPGjZFd2ke1ZxjhJZkM45Ec9GH9hv\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/ERC20Upgradeable.sol\":{\"keccak256\":\"0xa9311aeb22f459e57d4dac77ee76cf43fb28ad3215278456211b5852b0e9e970\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ebdf0d3e42bd25223e45a213311d6d7e177d56a2c541a78b58c0c9d10bbdfbf9\",\"dweb:/ipfs/QmfMyehJ6pxHrh7yL4793J6i7dofXnS2zH3cTtC8JdQMV9\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/IERC20Upgradeable.sol\":{\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c25f742ff154998d19a669e2508c3597b363e123ce9144cd0fcf6521229f401f\",\"dweb:/ipfs/QmQXRuFzStEWqeEPbhQU6cAg9PaSowxJVo4PDKyRod7dco\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/ERC20PermitUpgradeable.sol\":{\"keccak256\":\"0x3d159b9049d4ef465c1fb41f7ff7620f18f52bf6f8f3018bae4ed95c2df537d3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://38f7cfa624d878eec3c97e30dac64c6c00a79c65aa2799cebbf683e74488cd27\",\"dweb:/ipfs/QmdtMH3xSGXNqvBcndsxWCUfmjta6kebnUYwKasJZucTfP\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/ERC20VotesUpgradeable.sol\":{\"keccak256\":\"0x82d5c2e8d5c7209f5cd2e7a40807ba264cb8bc577db1b121eda5f14f62d609c2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://024b99222ec16e75ff1b719c8f0dacf2d8e26250b3c076bd184ac1dadae47492\",\"dweb:/ipfs/QmP11f3Dumw3CYg4ZtBLJrh8juULgodSuQfCqqgX5DqpJE\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\":{\"keccak256\":\"0x605434219ebbe4653f703640f06969faa5a1d78f0bfef878e5ddbb1ca369ceeb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4c9c634f99dd02d73ce7498b03a6305e251c05eeebb71457306561c1fab0fa7d\",\"dweb:/ipfs/QmbYRBbZHy8YoaQKXdPryiL3CSS7uUaRfRYi1TUj9cTqJQ\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"keccak256\":\"0x07e881de3b9f6d2c07909f193f24b96c7fe4ea60013260f3f25aecd8bab3c2f8\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1fed09b97ccb0ff9ba9b6a94224f1d489026bf6b4b7279bfe64fb6e8749dee4d\",\"dweb:/ipfs/QmcRAzaSP1UnGr4vrGkfJmB2L9aiTYoXfV1Lg9gqrVRWn8\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://310136ad60820af4177a11a61d77a3686faf5fca4942b600e08fc940db38396b\",\"dweb:/ipfs/QmbCzMNSTL7Zi7M4UCSqBrkHtp4jjxUnGbkneCZKdR1qeq\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x75097e35253e7fb282ee4d7f27a80eaacfa759923185bf17302a89cbc059c5ef\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8b06267c5f80bad727af3e48b1382333d591dad51376399ef2f6b0ee6d58bf95\",\"dweb:/ipfs/QmdU5La1agcQvghnfMpWZGDPz2TUDTCxUwTLKmuMRXBpAx\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/CountersUpgradeable.sol\":{\"keccak256\":\"0x798741e231b22b81e2dd2eddaaf8832dee4baf5cd8e2dbaa5c1dd12a1c053c4d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c41e8a7a906b8f362c8b760a44edadc61782008ea2ecf377ac5b5325bf6c3912\",\"dweb:/ipfs/QmcXr19zuH3YLzD6RZNE6UTzvsKSckdxZQnagPoDGkCHu2\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/StringsUpgradeable.sol\":{\"keccak256\":\"0xb96dc79b65b7c37937919dcdb356a969ce0aa2e8338322bf4dc027a3c9c9a7eb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f8613145881436fc0480fff22da4868d611e2b0c0c3da083334eb4362ce1945a\",\"dweb:/ipfs/QmPqpP3YeRbBdTJRe6Gv2eGsUaANf4J6RwTNRW36iYahfV\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/cryptography/ECDSAUpgradeable.sol\":{\"keccak256\":\"0xa014f65d84b02827055d99993ccdbfb4b56b2c9e91eb278d82a93330659d06e4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://50a7e716a74f3d48a7f549086faa94afcd58b9f18ac8e9f74af4571f3a1d8d5c\",\"dweb:/ipfs/QmTkDNWkq5o9Cv2jS7s6JvSmsPBkeunZhPe7Z2njGL31wo\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/cryptography/EIP712Upgradeable.sol\":{\"keccak256\":\"0x7077d7f3369b21f286840c0d69b09a8a6d3d6e522fff67bfc240fd0a6cdf178c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://0f59e7a19530bd6ee236285f9a87c930d27b73464f6b7398e29a6f4cfc2670ac\",\"dweb:/ipfs/QmVfN4gHvJNac7KiuhLhtgtbdDo5a6Mw5hMcwJkzYugq5R\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/math/MathUpgradeable.sol\":{\"keccak256\":\"0x2bc0007987c229ae7624eb29be6a9b84f6a6a5872f76248b15208b131ea41c4e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://2b2835c737d073ef8b82a4cc246495a9740f43e7ff2cf130906b2449ff9bfb91\",\"dweb:/ipfs/QmSCWfNoSvvTN57ic7o1RW6NqSxxGAqbBTnLKc7QHe27qB\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/math/SafeCastUpgradeable.sol\":{\"keccak256\":\"0xcef50f95b43b038aa40aed25b62fc45906c681a5c1d504a4fdcf3bc6330a8d4b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ef883699a00970d5469e502514e2854704cd53d7a49825078aa807a2f056315c\",\"dweb:/ipfs/QmRjpN9oxgw6zHCVjfWNB9MzaYpNPPgqu7Rrwqwabmhpis\"]},\"lib/openzeppelin-contracts-upgradeable/contracts/utils/math/SignedMathUpgradeable.sol\":{\"keccak256\":\"0x88f6b7bba3ee33eeb741f9a0f5bc98b6e6e352d0fe4905377bb328590f84095a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://88ace2d60f265752f18903d839910be4e4e104340b2957678585b812447825d4\",\"dweb:/ipfs/QmXFkNxMc3AAGzhs2wUEZyErWQjsvoTGyYjuU5oZkFki5Z\"]}},\"version\":1}", + "metadata": { + "compiler": { "version": "0.8.29+commit.ab55807c" }, + "language": "Solidity", + "output": { + "abi": [ + { + "inputs": [ + { "internalType": "address", "name": "owner", "type": "address", "indexed": true }, + { "internalType": "address", "name": "spender", "type": "address", "indexed": true }, + { "internalType": "uint256", "name": "value", "type": "uint256", "indexed": false } + ], + "type": "event", + "name": "Approval", + "anonymous": false + }, + { + "inputs": [ + { "internalType": "address", "name": "delegator", "type": "address", "indexed": true }, + { "internalType": "address", "name": "fromDelegate", "type": "address", "indexed": true }, + { "internalType": "address", "name": "toDelegate", "type": "address", "indexed": true } + ], + "type": "event", + "name": "DelegateChanged", + "anonymous": false + }, + { + "inputs": [ + { "internalType": "address", "name": "delegate", "type": "address", "indexed": true }, + { "internalType": "uint256", "name": "previousBalance", "type": "uint256", "indexed": false }, + { "internalType": "uint256", "name": "newBalance", "type": "uint256", "indexed": false } + ], + "type": "event", + "name": "DelegateVotesChanged", + "anonymous": false + }, + { "inputs": [], "type": "event", "name": "EIP712DomainChanged", "anonymous": false }, + { + "inputs": [{ "internalType": "uint8", "name": "version", "type": "uint8", "indexed": false }], + "type": "event", + "name": "Initialized", + "anonymous": false + }, + { + "inputs": [ + { "internalType": "address", "name": "from", "type": "address", "indexed": true }, + { "internalType": "address", "name": "to", "type": "address", "indexed": true }, + { "internalType": "uint256", "name": "value", "type": "uint256", "indexed": false } + ], + "type": "event", + "name": "Transfer", + "anonymous": false + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "CLOCK_MODE", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "DOMAIN_SEPARATOR", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }] + }, + { + "inputs": [ + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "spender", "type": "address" } + ], + "stateMutability": "view", + "type": "function", + "name": "allowance", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }] + }, + { + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "approve", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }] + }, + { + "inputs": [{ "internalType": "address", "name": "account", "type": "address" }], + "stateMutability": "view", + "type": "function", + "name": "balanceOf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }] + }, + { + "inputs": [ + { "internalType": "address", "name": "account", "type": "address" }, + { "internalType": "uint32", "name": "pos", "type": "uint32" } + ], + "stateMutability": "view", + "type": "function", + "name": "checkpoints", + "outputs": [ + { + "internalType": "struct ERC20VotesUpgradeable.Checkpoint", + "name": "", + "type": "tuple", + "components": [ + { "internalType": "uint32", "name": "fromBlock", "type": "uint32" }, + { "internalType": "uint224", "name": "votes", "type": "uint224" } + ] + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "clock", + "outputs": [{ "internalType": "uint48", "name": "", "type": "uint48" }] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "decimals", + "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }] + }, + { + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "subtractedValue", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "decreaseAllowance", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }] + }, + { + "inputs": [{ "internalType": "address", "name": "delegatee", "type": "address" }], + "stateMutability": "nonpayable", + "type": "function", + "name": "delegate" + }, + { + "inputs": [ + { "internalType": "address", "name": "delegatee", "type": "address" }, + { "internalType": "uint256", "name": "nonce", "type": "uint256" }, + { "internalType": "uint256", "name": "expiry", "type": "uint256" }, + { "internalType": "uint8", "name": "v", "type": "uint8" }, + { "internalType": "bytes32", "name": "r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "s", "type": "bytes32" } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "delegateBySig" + }, + { + "inputs": [{ "internalType": "address", "name": "account", "type": "address" }], + "stateMutability": "view", + "type": "function", + "name": "delegates", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "eip712Domain", + "outputs": [ + { "internalType": "bytes1", "name": "fields", "type": "bytes1" }, + { "internalType": "string", "name": "name", "type": "string" }, + { "internalType": "string", "name": "version", "type": "string" }, + { "internalType": "uint256", "name": "chainId", "type": "uint256" }, + { "internalType": "address", "name": "verifyingContract", "type": "address" }, + { "internalType": "bytes32", "name": "salt", "type": "bytes32" }, + { "internalType": "uint256[]", "name": "extensions", "type": "uint256[]" } + ] + }, + { + "inputs": [{ "internalType": "uint256", "name": "timepoint", "type": "uint256" }], + "stateMutability": "view", + "type": "function", + "name": "getPastTotalSupply", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }] + }, + { + "inputs": [ + { "internalType": "address", "name": "account", "type": "address" }, + { "internalType": "uint256", "name": "timepoint", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function", + "name": "getPastVotes", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }] + }, + { + "inputs": [{ "internalType": "address", "name": "account", "type": "address" }], + "stateMutability": "view", + "type": "function", + "name": "getVotes", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }] + }, + { + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "addedValue", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "increaseAllowance", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "name", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }] + }, + { + "inputs": [{ "internalType": "address", "name": "owner", "type": "address" }], + "stateMutability": "view", + "type": "function", + "name": "nonces", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }] + }, + { + "inputs": [{ "internalType": "address", "name": "account", "type": "address" }], + "stateMutability": "view", + "type": "function", + "name": "numCheckpoints", + "outputs": [{ "internalType": "uint32", "name": "", "type": "uint32" }] + }, + { + "inputs": [ + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "value", "type": "uint256" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" }, + { "internalType": "uint8", "name": "v", "type": "uint8" }, + { "internalType": "bytes32", "name": "r", "type": "bytes32" }, + { "internalType": "bytes32", "name": "s", "type": "bytes32" } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "permit" + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "symbol", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "totalSupply", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }] + }, + { + "inputs": [ + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "transfer", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }] + }, + { + "inputs": [ + { "internalType": "address", "name": "from", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "transferFrom", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }] + } + ], + "devdoc": { + "kind": "dev", + "methods": { + "CLOCK_MODE()": { "details": "Description of the clock" }, + "DOMAIN_SEPARATOR()": { + "details": "Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}." + }, + "allowance(address,address)": { "details": "See {IERC20-allowance}." }, + "approve(address,uint256)": { + "details": "See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address." + }, + "balanceOf(address)": { "details": "See {IERC20-balanceOf}." }, + "checkpoints(address,uint32)": { "details": "Get the `pos`-th checkpoint for `account`." }, + "clock()": { + "details": "Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting)." + }, + "decimals()": { + "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the default value returned by this function, unless it's overridden. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." + }, + "decreaseAllowance(address,uint256)": { + "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`." + }, + "delegate(address)": { "details": "Delegate votes from the sender to `delegatee`." }, + "delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)": { "details": "Delegates votes from signer to `delegatee`" }, + "delegates(address)": { "details": "Get the address `account` is currently delegating to." }, + "eip712Domain()": { "details": "See {EIP-5267}. _Available since v4.9._" }, + "getPastTotalSupply(uint256)": { + "details": "Retrieve the `totalSupply` at the end of `timepoint`. Note, this value is the sum of all balances. It is NOT the sum of all the delegated votes! Requirements: - `timepoint` must be in the past" + }, + "getPastVotes(address,uint256)": { + "details": "Retrieve the number of votes for `account` at the end of `timepoint`. Requirements: - `timepoint` must be in the past" + }, + "getVotes(address)": { "details": "Gets the current votes balance for `account`" }, + "increaseAllowance(address,uint256)": { + "details": "Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address." + }, + "name()": { "details": "Returns the name of the token." }, + "nonces(address)": { + "details": "Returns the current nonce for `owner`. This value must be included whenever a signature is generated for {permit}. Every successful call to {permit} increases ``owner``'s nonce by one. This prevents a signature from being used multiple times." + }, + "numCheckpoints(address)": { "details": "Get number of checkpoints for `account`." }, + "permit(address,address,uint256,uint256,uint8,bytes32,bytes32)": { + "details": "Sets `value` as the allowance of `spender` over ``owner``'s tokens, given ``owner``'s signed approval. IMPORTANT: The same issues {IERC20-approve} has related to transaction ordering also apply here. Emits an {Approval} event. Requirements: - `spender` cannot be the zero address. - `deadline` must be a timestamp in the future. - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` over the EIP712-formatted function arguments. - the signature must use ``owner``'s current nonce (see {nonces}). For more information on the signature format, see the https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP section]. CAUTION: See Security Considerations above." + }, + "symbol()": { "details": "Returns the symbol of the token, usually a shorter version of the name." }, + "totalSupply()": { "details": "See {IERC20-totalSupply}." }, + "transfer(address,uint256)": { + "details": "See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`." + }, + "transferFrom(address,address,uint256)": { + "details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`." + } + }, + "version": 1 + }, + "userdoc": { "kind": "user", "methods": {}, "version": 1 } + }, + "settings": { + "remappings": [ + "@aragon/osx-commons-contracts/=lib/osx-commons/contracts/", + "@aragon/osx/=lib/osx/packages/contracts/src/", + "@aragon/token-voting-plugin/=node_modules/@aragon/token-voting-plugin/src/", + "@enclave-e3/contracts/=node_modules/@enclave-e3/contracts/", + "@ensdomains/buffer/=lib/buffer/", + "@ensdomains/ens-contracts/=lib/ens-contracts/", + "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", + "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", + "ds-test/=lib/openzeppelin-contracts-upgradeable/lib/forge-std/lib/ds-test/src/", + "ens-contracts/=lib/ens-contracts/contracts/", + "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", + "forge-std/=lib/forge-std/src/", + "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/", + "osx-commons/=lib/osx-commons/", + "osx/=lib/osx/" + ], + "optimizer": { "enabled": true, "runs": 200 }, + "metadata": { "bytecodeHash": "ipfs" }, + "compilationTarget": { + "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/ERC20VotesUpgradeable.sol": "ERC20VotesUpgradeable" + }, + "evmVersion": "cancun", + "libraries": {} + }, + "sources": { + "lib/openzeppelin-contracts-upgradeable/contracts/governance/utils/IVotesUpgradeable.sol": { + "keccak256": "0x2d600bbef9320309cd2a86c1d087eb9d6dbcc00430713ee54bbc5c5a2a11ba31", + "urls": [ + "bzz-raw://52a5380b861d676adef15f33f8f643e236a1acb2d9456beb4065307eaa22bc2a", + "dweb:/ipfs/QmdwSfxrafQubVvCoQCU5T7bbPR8JDWU1WotSDXSiUdm33" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/interfaces/IERC5267Upgradeable.sol": { + "keccak256": "0xe562dab443278837fa50faddb76743399e942181881db8dccaea3bd1712994db", + "urls": [ + "bzz-raw://79ebe0e661396045cefe94f4256398cf632756d779a6871319db374c9eb128c9", + "dweb:/ipfs/QmfCTCivb9fFhyCX8hzushzcKunvKL2N9RDsnRNdvbd11M" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/interfaces/IERC5805Upgradeable.sol": { + "keccak256": "0x19848eec9045c8b91f1ab6b1853966443e3e36bcbc307593ed37a9f0df179d69", + "urls": [ + "bzz-raw://a07972c1330ee99a5d051b393260e01412ac4c14c7bc4d75d80b7cce291a6412", + "dweb:/ipfs/QmQx1ZiAo4AbSobN41c1xUEtyX1QejydWCmY7Sj3H5aDNv" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/interfaces/IERC6372Upgradeable.sol": { + "keccak256": "0x3026befd6d69d1b46960bdc35a2ad37c0e1352f26983ee3728dd61fd32aa308a", + "urls": [ + "bzz-raw://c2001b7209fd4920ec7674f194db7fe163dfea7a7af2dd25fe6c0e5a94dc595c", + "dweb:/ipfs/QmXX2zTFyiNWoDxivV3trKcKWifAENMqNAB34NgjWq5feX" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol": { + "keccak256": "0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794", + "urls": [ + "bzz-raw://f103ee2e4aecd37aac6ceefe670709cdd7613dee25fa2d4d9feaf7fc0aaa155e", + "dweb:/ipfs/QmRiNZLoJk5k3HPMYGPGjZFd2ke1ZxjhJZkM45Ec9GH9hv" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/ERC20Upgradeable.sol": { + "keccak256": "0xa9311aeb22f459e57d4dac77ee76cf43fb28ad3215278456211b5852b0e9e970", + "urls": [ + "bzz-raw://ebdf0d3e42bd25223e45a213311d6d7e177d56a2c541a78b58c0c9d10bbdfbf9", + "dweb:/ipfs/QmfMyehJ6pxHrh7yL4793J6i7dofXnS2zH3cTtC8JdQMV9" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/IERC20Upgradeable.sol": { + "keccak256": "0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f", + "urls": [ + "bzz-raw://c25f742ff154998d19a669e2508c3597b363e123ce9144cd0fcf6521229f401f", + "dweb:/ipfs/QmQXRuFzStEWqeEPbhQU6cAg9PaSowxJVo4PDKyRod7dco" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/ERC20PermitUpgradeable.sol": { + "keccak256": "0x3d159b9049d4ef465c1fb41f7ff7620f18f52bf6f8f3018bae4ed95c2df537d3", + "urls": [ + "bzz-raw://38f7cfa624d878eec3c97e30dac64c6c00a79c65aa2799cebbf683e74488cd27", + "dweb:/ipfs/QmdtMH3xSGXNqvBcndsxWCUfmjta6kebnUYwKasJZucTfP" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/ERC20VotesUpgradeable.sol": { + "keccak256": "0x82d5c2e8d5c7209f5cd2e7a40807ba264cb8bc577db1b121eda5f14f62d609c2", + "urls": [ + "bzz-raw://024b99222ec16e75ff1b719c8f0dacf2d8e26250b3c076bd184ac1dadae47492", + "dweb:/ipfs/QmP11f3Dumw3CYg4ZtBLJrh8juULgodSuQfCqqgX5DqpJE" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/IERC20MetadataUpgradeable.sol": { + "keccak256": "0x605434219ebbe4653f703640f06969faa5a1d78f0bfef878e5ddbb1ca369ceeb", + "urls": [ + "bzz-raw://4c9c634f99dd02d73ce7498b03a6305e251c05eeebb71457306561c1fab0fa7d", + "dweb:/ipfs/QmbYRBbZHy8YoaQKXdPryiL3CSS7uUaRfRYi1TUj9cTqJQ" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/IERC20PermitUpgradeable.sol": { + "keccak256": "0x07e881de3b9f6d2c07909f193f24b96c7fe4ea60013260f3f25aecd8bab3c2f8", + "urls": [ + "bzz-raw://1fed09b97ccb0ff9ba9b6a94224f1d489026bf6b4b7279bfe64fb6e8749dee4d", + "dweb:/ipfs/QmcRAzaSP1UnGr4vrGkfJmB2L9aiTYoXfV1Lg9gqrVRWn8" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol": { + "keccak256": "0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422", + "urls": [ + "bzz-raw://310136ad60820af4177a11a61d77a3686faf5fca4942b600e08fc940db38396b", + "dweb:/ipfs/QmbCzMNSTL7Zi7M4UCSqBrkHtp4jjxUnGbkneCZKdR1qeq" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol": { + "keccak256": "0x75097e35253e7fb282ee4d7f27a80eaacfa759923185bf17302a89cbc059c5ef", + "urls": [ + "bzz-raw://8b06267c5f80bad727af3e48b1382333d591dad51376399ef2f6b0ee6d58bf95", + "dweb:/ipfs/QmdU5La1agcQvghnfMpWZGDPz2TUDTCxUwTLKmuMRXBpAx" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/utils/CountersUpgradeable.sol": { + "keccak256": "0x798741e231b22b81e2dd2eddaaf8832dee4baf5cd8e2dbaa5c1dd12a1c053c4d", + "urls": [ + "bzz-raw://c41e8a7a906b8f362c8b760a44edadc61782008ea2ecf377ac5b5325bf6c3912", + "dweb:/ipfs/QmcXr19zuH3YLzD6RZNE6UTzvsKSckdxZQnagPoDGkCHu2" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/utils/StringsUpgradeable.sol": { + "keccak256": "0xb96dc79b65b7c37937919dcdb356a969ce0aa2e8338322bf4dc027a3c9c9a7eb", + "urls": [ + "bzz-raw://f8613145881436fc0480fff22da4868d611e2b0c0c3da083334eb4362ce1945a", + "dweb:/ipfs/QmPqpP3YeRbBdTJRe6Gv2eGsUaANf4J6RwTNRW36iYahfV" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/utils/cryptography/ECDSAUpgradeable.sol": { + "keccak256": "0xa014f65d84b02827055d99993ccdbfb4b56b2c9e91eb278d82a93330659d06e4", + "urls": [ + "bzz-raw://50a7e716a74f3d48a7f549086faa94afcd58b9f18ac8e9f74af4571f3a1d8d5c", + "dweb:/ipfs/QmTkDNWkq5o9Cv2jS7s6JvSmsPBkeunZhPe7Z2njGL31wo" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/utils/cryptography/EIP712Upgradeable.sol": { + "keccak256": "0x7077d7f3369b21f286840c0d69b09a8a6d3d6e522fff67bfc240fd0a6cdf178c", + "urls": [ + "bzz-raw://0f59e7a19530bd6ee236285f9a87c930d27b73464f6b7398e29a6f4cfc2670ac", + "dweb:/ipfs/QmVfN4gHvJNac7KiuhLhtgtbdDo5a6Mw5hMcwJkzYugq5R" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/utils/math/MathUpgradeable.sol": { + "keccak256": "0x2bc0007987c229ae7624eb29be6a9b84f6a6a5872f76248b15208b131ea41c4e", + "urls": [ + "bzz-raw://2b2835c737d073ef8b82a4cc246495a9740f43e7ff2cf130906b2449ff9bfb91", + "dweb:/ipfs/QmSCWfNoSvvTN57ic7o1RW6NqSxxGAqbBTnLKc7QHe27qB" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/utils/math/SafeCastUpgradeable.sol": { + "keccak256": "0xcef50f95b43b038aa40aed25b62fc45906c681a5c1d504a4fdcf3bc6330a8d4b", + "urls": [ + "bzz-raw://ef883699a00970d5469e502514e2854704cd53d7a49825078aa807a2f056315c", + "dweb:/ipfs/QmRjpN9oxgw6zHCVjfWNB9MzaYpNPPgqu7Rrwqwabmhpis" + ], + "license": "MIT" + }, + "lib/openzeppelin-contracts-upgradeable/contracts/utils/math/SignedMathUpgradeable.sol": { + "keccak256": "0x88f6b7bba3ee33eeb741f9a0f5bc98b6e6e352d0fe4905377bb328590f84095a", + "urls": [ + "bzz-raw://88ace2d60f265752f18903d839910be4e4e104340b2957678585b812447825d4", + "dweb:/ipfs/QmXFkNxMc3AAGzhs2wUEZyErWQjsvoTGyYjuU5oZkFki5Z" + ], + "license": "MIT" + } + }, + "version": 1 + }, + "id": 48 +} diff --git a/examples/CRISP/sdk/src/index.ts b/examples/CRISP/sdk/src/index.ts index a2dc538db4..486bc21076 100644 --- a/examples/CRISP/sdk/src/index.ts +++ b/examples/CRISP/sdk/src/index.ts @@ -7,5 +7,6 @@ export * from './token' export * from './state' export * from './constants' +export * from './utils' -export type { IRoundDetails, ITokenDetails } from './types' +export type { IRoundDetails, IRoundDetailsResponse, ITokenDetails, IMerkleProof } from './types' diff --git a/examples/CRISP/sdk/src/token.ts b/examples/CRISP/sdk/src/token.ts index e0c10ded71..9a4b759d64 100644 --- a/examples/CRISP/sdk/src/token.ts +++ b/examples/CRISP/sdk/src/token.ts @@ -6,12 +6,16 @@ import { CRISP_SERVER_TOKEN_TREE_ENDPOINT } from './constants' +import ERC20Votes from './artifacts/ERC20Votes.json' +import { createPublicClient, http } from 'viem' +import { localhost, sepolia } from 'viem/chains' + /** * Get the merkle tree data from the CRISP server * @param serverUrl - The base URL of the CRISP server * @param e3Id - The e3Id of the round */ -export const getTreeData = async (serverUrl: string, e3Id: number) => { +export const getTreeData = async (serverUrl: string, e3Id: number): Promise => { const response = await fetch(`${serverUrl}/${CRISP_SERVER_TOKEN_TREE_ENDPOINT}`, { method: 'POST', headers: { @@ -20,17 +24,50 @@ export const getTreeData = async (serverUrl: string, e3Id: number) => { body: JSON.stringify({ round_id: e3Id }), }) - const hashes = await response.json() + const hashes = (await response.json()) as string[] - return hashes + // Convert hex strings to BigInts + return hashes.map((hash) => { + // Ensure the hash is treated as a hex string + if (!hash.startsWith('0x')) { + return BigInt('0x' + hash) + } + return BigInt(hash) + }) } -/** - * Generate a Merkle proof for a given address to prove inclusion in the voters' list - */ -export const generateMerkleProof = () => {} - /** * Get the token balance at a specific block for a given address + * @param voterAddress - The address of the voter + * @param tokenAddress - The address of the token contract + * @param snapshotBlock - The block number at which to get the balance + * @param chainId - The chain ID of the network + * @returns The token balance as a bigint */ -export const getBalanceAt = () => {} +export const getBalanceAt = async (voterAddress: string, tokenAddress: string, snapshotBlock: number, chainId: number): Promise => { + let chain + switch (chainId) { + case 11155111: + chain = sepolia + break + case 31337: + chain = localhost + break + default: + throw new Error('Unsupported chainId') + } + + const publicClient = createPublicClient({ + transport: http(), + chain, + }) + + const balance = (await publicClient.readContract({ + address: tokenAddress as `0x${string}`, + abi: ERC20Votes.abi, + functionName: 'getPastVotes', + args: [voterAddress as `0x${string}`, BigInt(snapshotBlock)], + })) as bigint + + return balance +} diff --git a/examples/CRISP/sdk/src/types.ts b/examples/CRISP/sdk/src/types.ts index 8daca5b4ea..fccada491e 100644 --- a/examples/CRISP/sdk/src/types.ts +++ b/examples/CRISP/sdk/src/types.ts @@ -4,6 +4,8 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. +import type { LeanIMTMerkleProof } from '@zk-kit/lean-imt' + /** * Interface representing the details of a specific round returned by the CRISP server */ @@ -50,3 +52,12 @@ export interface ITokenDetails { threshold: bigint snapshotBlock: bigint } + +/** + * Interface representing a Merkle proof + */ +export interface IMerkleProof { + leaf: bigint + index: number + proof: LeanIMTMerkleProof +} diff --git a/examples/CRISP/sdk/src/utils.ts b/examples/CRISP/sdk/src/utils.ts new file mode 100644 index 0000000000..701e41210c --- /dev/null +++ b/examples/CRISP/sdk/src/utils.ts @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +import { poseidon2 } from 'poseidon-lite' +import { LeanIMT } from '@zk-kit/lean-imt' + +import type { IMerkleProof } from './types' + +/** + * Hash a leaf node for the Merkle tree + * @param address The voter's address + * @param balance The voter's balance + * @returns The hashed leaf as a bigint + */ +export const hashLeaf = (address: string, balance: string): bigint => { + return poseidon2([address, balance]) +} + +/** + * Generate a new LeanIMT with the leaves provided + * @param leaves The leaves of the Merkle tree + * @returns the generated Merkle tree + */ +export const generateMerkleTree = (leaves: bigint[]): LeanIMT => { + return new LeanIMT((a, b) => poseidon2([a, b]), leaves) +} + +/** + * Generate a Merkle proof for a given address to prove inclusion in the voters' list + * @param threshold The minimum balance required to be eligible + * @param balance The voter's balance + * @param address The voter's address + * @param leaves The leaves of the Merkle tree + */ +export const generateMerkleProof = (threshold: number, balance: number, address: string, leaves: bigint[]): IMerkleProof => { + if (balance < threshold) { + throw new Error('Balance is below the threshold') + } + + const leaf = hashLeaf(address, balance.toString()) + + const index = leaves.findIndex((l) => l === leaf) + + if (index === -1) { + throw new Error('Leaf not found in the tree') + } + + const tree = generateMerkleTree(leaves) + + const proof = tree.generateProof(index) + + return { + leaf, + index, + proof, + } +} diff --git a/examples/CRISP/sdk/tests/utils.test.ts b/examples/CRISP/sdk/tests/utils.test.ts new file mode 100644 index 0000000000..182b7bd67b --- /dev/null +++ b/examples/CRISP/sdk/tests/utils.test.ts @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +import { expect, describe, it, beforeAll } from 'vitest' +import { generateMerkleProof, generateMerkleTree, hashLeaf } from '../src/utils' +import { getTreeData } from '../src' +import { CRISP_SERVER_URL } from './constants' + +describe('Utils', () => { + let leaves: bigint[] + + beforeAll(async () => { + leaves = await getTreeData(CRISP_SERVER_URL, 0) + }) + + describe('hashLeaf', () => { + it('should return a bigint hash of the two values', () => { + const leaf = hashLeaf('0x1234567890123456789012345678901234567890', '1000') + expect(typeof leaf).toBe('bigint') + }) + }) + + describe('generateMerkleTree', () => { + it('should generate a merkle tree', () => { + const tree = generateMerkleTree(leaves) + expect(tree.root).toBeDefined() + }) + }) + + describe('generateMerkleProof', () => { + const address = '0x1234567890123456789012345678901234567890' + const balance = 1000 + it('should generate a merkle proof for a leaf', () => { + const proof = generateMerkleProof(0, balance, address, leaves) + expect(proof.leaf).toBe(hashLeaf(address, balance.toString())) + }) + it('should throw if the leaf does not exist in the tree', () => { + expect(() => generateMerkleProof(0, balance, address, [])).toThrow('Leaf not found in the tree') + expect(() => generateMerkleProof(0, 999, address, leaves)).toThrow('Leaf not found in the tree') + }) + }) +}) diff --git a/examples/CRISP/sdk/tsconfig.json b/examples/CRISP/sdk/tsconfig.json index 90e5742226..935a5fca15 100644 --- a/examples/CRISP/sdk/tsconfig.json +++ b/examples/CRISP/sdk/tsconfig.json @@ -9,5 +9,5 @@ "outDir": "dist", "declaration": true }, - "include": ["src/**/*.ts"] + "include": ["src/**/*.ts", "src/**/*.json"] } diff --git a/examples/CRISP/server/src/server/repo.rs b/examples/CRISP/server/src/server/repo.rs index 6a96a081a3..3ead14e610 100644 --- a/examples/CRISP/server/src/server/repo.rs +++ b/examples/CRISP/server/src/server/repo.rs @@ -244,6 +244,7 @@ impl CrispE3Repository { pub async fn set_token_holder_hashes(&mut self, hashes: Vec) -> Result<()> { let key = self.crisp_key(); + self.store .modify(&key, |e3_obj: Option| { e3_obj.map(|mut e| { @@ -259,7 +260,6 @@ impl CrispE3Repository { pub async fn get_token_holder_hashes(&self) -> Result> { let e3_crisp = self.get_crisp().await?; - Ok(e3_crisp.token_holder_hashes) } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 784cc96ead..02c17d65aa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -332,6 +332,16 @@ importers: version: 3.5.0(vite@5.4.19(@types/node@22.7.5)) examples/CRISP/sdk: + dependencies: + '@zk-kit/lean-imt': + specifier: ^2.2.4 + version: 2.2.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + poseidon-lite: + specifier: ^0.3.0 + version: 0.3.0 + viem: + specifier: 2.30.6 + version: 2.30.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.76) devDependencies: '@types/chai': specifier: ^5.2.2