From 28dba79fe6611385cabad967ca55851ad82af6d9 Mon Sep 17 00:00:00 2001 From: ross <92001561+z0r0z@users.noreply.github.com> Date: Tue, 23 Jul 2024 07:47:30 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=95=AF=EF=B8=8F=E2=8B=86.=CB=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gas-snapshot | 4 +- README.md | 2 + abi/Summoner.json | 82 +++++++++++++++++++ docs/src/README.md | 2 + docs/src/SUMMARY.md | 2 + docs/src/src/Dagon.sol/contract.Dagon.md | 2 +- docs/src/src/Dagon.sol/interface.IAuth.md | 2 +- docs/src/src/Dagon.sol/interface.IOwnable.md | 2 +- docs/src/src/README.md | 2 + .../src/src/Summoner.sol/contract.Summoner.md | 6 +- .../src/Summoner.sol/interface.IAccounts.md | 2 +- lib/forge-std | 2 +- lib/solady | 2 +- src/Summoner.sol | 45 ++++++++++ 14 files changed, 146 insertions(+), 11 deletions(-) create mode 100644 abi/Summoner.json create mode 100644 src/Summoner.sol diff --git a/.gas-snapshot b/.gas-snapshot index 30c5575..2413c86 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,7 +1,7 @@ DagonTest:testBurn(address,uint96) (runs: 260, μ: 138940, ~: 138940) DagonTest:testDeploy() (gas: 2367822) -DagonTest:testFailBurnOverBalance(address,uint96) (runs: 260, μ: 153887, ~: 154347) -DagonTest:testFailBurnOverThreshold(address,uint96) (runs: 260, μ: 185162, ~: 185622) +DagonTest:testFailBurnOverBalance(address,uint96) (runs: 260, μ: 153811, ~: 154347) +DagonTest:testFailBurnOverThreshold(address,uint96) (runs: 260, μ: 185086, ~: 185622) DagonTest:testFailInvalidThresholdExceedsSupply() (gas: 124461) DagonTest:testFailInvalidThresholdExceedsSupply2() (gas: 129541) DagonTest:testFailInvalidThresholdNull() (gas: 124442) diff --git a/README.md b/README.md index 93fa6f2..f884137 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ Chains | Address | ----------------|-----------------------------------------| Ethereum, Arbitrum, Optimism, Base, Blast, Zora, Gnosis, Polygon, Avalanche and BNB (& testnets) | [0x000000000000FEb893BB5D63bA33323EdCC237cE](https://etherscan.io/address/0x000000000000FEb893BB5D63bA33323EdCC237cE#code) | +> Summoner: [0x000000004356af01f3b800d93b0066e4b71e3609](https://etherscan.io/address/0x000000004356af01f3b800d93b0066e4b71e3609#code) + Dagon deployments are generated as [efficient create2 addresses](https://medium.com/coinmonks/on-efficient-ethereum-addresses-3fef0596e263) through the [canonical create2 factory](https://etherscan.io/address/0x0000000000ffe8b47b3e2130213b802212439497#code). As such they share the same exact address and code on every blockchain. ## Premise diff --git a/abi/Summoner.json b/abi/Summoner.json new file mode 100644 index 0000000..123a9fa --- /dev/null +++ b/abi/Summoner.json @@ -0,0 +1,82 @@ +[ + { + "type": "function", + "name": "summon", + "inputs": [ + { + "name": "summoners", + "type": "tuple[]", + "internalType": "struct Summoner.Ownership[]", + "components": [ + { + "name": "owner", + "type": "address", + "internalType": "address" + }, + { + "name": "shares", + "type": "uint96", + "internalType": "uint96" + } + ] + }, + { + "name": "threshold", + "type": "uint88", + "internalType": "uint88" + }, + { + "name": "locked", + "type": "bool", + "internalType": "bool" + }, + { + "name": "salt", + "type": "bytes12", + "internalType": "bytes12" + } + ], + "outputs": [ + { + "name": "account", + "type": "address", + "internalType": "contract IAccounts" + } + ], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "summonForToken", + "inputs": [ + { + "name": "token", + "type": "address", + "internalType": "address" + }, + { + "name": "standard", + "type": "uint8", + "internalType": "enum Summoner.Standard" + }, + { + "name": "threshold", + "type": "uint88", + "internalType": "uint88" + }, + { + "name": "salt", + "type": "bytes12", + "internalType": "bytes12" + } + ], + "outputs": [ + { + "name": "account", + "type": "address", + "internalType": "contract IAccounts" + } + ], + "stateMutability": "payable" + } + ] \ No newline at end of file diff --git a/docs/src/README.md b/docs/src/README.md index 93fa6f2..f884137 100644 --- a/docs/src/README.md +++ b/docs/src/README.md @@ -11,6 +11,8 @@ Chains | Address | ----------------|-----------------------------------------| Ethereum, Arbitrum, Optimism, Base, Blast, Zora, Gnosis, Polygon, Avalanche and BNB (& testnets) | [0x000000000000FEb893BB5D63bA33323EdCC237cE](https://etherscan.io/address/0x000000000000FEb893BB5D63bA33323EdCC237cE#code) | +> Summoner: [0x000000004356af01f3b800d93b0066e4b71e3609](https://etherscan.io/address/0x000000004356af01f3b800d93b0066e4b71e3609#code) + Dagon deployments are generated as [efficient create2 addresses](https://medium.com/coinmonks/on-efficient-ethereum-addresses-3fef0596e263) through the [canonical create2 factory](https://etherscan.io/address/0x0000000000ffe8b47b3e2130213b802212439497#code). As such they share the same exact address and code on every blockchain. ## Premise diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 6d3d9be..e915708 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -4,3 +4,5 @@ - [Dagon](src/Dagon.sol/contract.Dagon.md) - [IAuth](src/Dagon.sol/interface.IAuth.md) - [IOwnable](src/Dagon.sol/interface.IOwnable.md) + - [Summoner](src/Summoner.sol/contract.Summoner.md) + - [IAccounts](src/Summoner.sol/interface.IAccounts.md) diff --git a/docs/src/src/Dagon.sol/contract.Dagon.md b/docs/src/src/Dagon.sol/contract.Dagon.md index 2b2236c..6b60a31 100644 --- a/docs/src/src/Dagon.sol/contract.Dagon.md +++ b/docs/src/src/Dagon.sol/contract.Dagon.md @@ -1,5 +1,5 @@ # Dagon -[Git Source](https://github.com/Moloch-Mystics/dagon/blob/405e4eb5a2a407d3f2421047d8b8f778ad336343/src/Dagon.sol) +[Git Source](https://github.com/Moloch-Mystics/dagon/blob/d39dde7073476515dbf75345b60f2ea3d623186a/src/Dagon.sol) **Inherits:** ERC6909 diff --git a/docs/src/src/Dagon.sol/interface.IAuth.md b/docs/src/src/Dagon.sol/interface.IAuth.md index 94f9b70..84f3165 100644 --- a/docs/src/src/Dagon.sol/interface.IAuth.md +++ b/docs/src/src/Dagon.sol/interface.IAuth.md @@ -1,5 +1,5 @@ # IAuth -[Git Source](https://github.com/Moloch-Mystics/dagon/blob/405e4eb5a2a407d3f2421047d8b8f778ad336343/src/Dagon.sol) +[Git Source](https://github.com/Moloch-Mystics/dagon/blob/d39dde7073476515dbf75345b60f2ea3d623186a/src/Dagon.sol) Simple authority interface for contracts. diff --git a/docs/src/src/Dagon.sol/interface.IOwnable.md b/docs/src/src/Dagon.sol/interface.IOwnable.md index e862b7f..f08847c 100644 --- a/docs/src/src/Dagon.sol/interface.IOwnable.md +++ b/docs/src/src/Dagon.sol/interface.IOwnable.md @@ -1,5 +1,5 @@ # IOwnable -[Git Source](https://github.com/Moloch-Mystics/dagon/blob/405e4eb5a2a407d3f2421047d8b8f778ad336343/src/Dagon.sol) +[Git Source](https://github.com/Moloch-Mystics/dagon/blob/d39dde7073476515dbf75345b60f2ea3d623186a/src/Dagon.sol) Simple ownership interface for handover requests. diff --git a/docs/src/src/README.md b/docs/src/src/README.md index 675a9ca..6b358fb 100644 --- a/docs/src/src/README.md +++ b/docs/src/src/README.md @@ -4,3 +4,5 @@ - [Dagon](Dagon.sol/contract.Dagon.md) - [IAuth](Dagon.sol/interface.IAuth.md) - [IOwnable](Dagon.sol/interface.IOwnable.md) +- [Summoner](Summoner.sol/contract.Summoner.md) +- [IAccounts](Summoner.sol/interface.IAccounts.md) diff --git a/docs/src/src/Summoner.sol/contract.Summoner.md b/docs/src/src/Summoner.sol/contract.Summoner.md index 5a316a7..dd05fdd 100644 --- a/docs/src/src/Summoner.sol/contract.Summoner.md +++ b/docs/src/src/Summoner.sol/contract.Summoner.md @@ -1,5 +1,5 @@ # Summoner -[Git Source](https://github.com/Moloch-Mystics/dagon/blob/efc921a89c26d7bf4ef258e73ffcf64e1bdef80a/src/Summoner.sol) +[Git Source](https://github.com/Moloch-Mystics/dagon/blob/d39dde7073476515dbf75345b60f2ea3d623186a/src/Summoner.sol) Simple summoner for Dagon (𒀭) group accounts. @@ -8,14 +8,14 @@ Simple summoner for Dagon (𒀭) group accounts. ### DAGON ```solidity -address internal constant DAGON = 0x0000000000001ADDcB933DD5028159dc965b5b7f; +address internal constant DAGON = 0x000000000000FEb893BB5D63bA33323EdCC237cE; ``` ### FACTORY ```solidity -IAccounts internal constant FACTORY = IAccounts(0x000000000000dD366cc2E4432bB998e41DFD47C7); +IAccounts internal constant FACTORY = IAccounts(0x0000000000009f1E546FC4A8F68eB98031846cb8); ``` diff --git a/docs/src/src/Summoner.sol/interface.IAccounts.md b/docs/src/src/Summoner.sol/interface.IAccounts.md index 4b56b00..c48e46e 100644 --- a/docs/src/src/Summoner.sol/interface.IAccounts.md +++ b/docs/src/src/Summoner.sol/interface.IAccounts.md @@ -1,5 +1,5 @@ # IAccounts -[Git Source](https://github.com/Moloch-Mystics/dagon/blob/efc921a89c26d7bf4ef258e73ffcf64e1bdef80a/src/Summoner.sol) +[Git Source](https://github.com/Moloch-Mystics/dagon/blob/d39dde7073476515dbf75345b60f2ea3d623186a/src/Summoner.sol) *Simple interface for Nani (𒀭) user account creation and setup.* diff --git a/lib/forge-std b/lib/forge-std index 07263d1..c28115d 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit 07263d193d621c4b2b0ce8b4d54af58f6957d97d +Subproject commit c28115db8d90ebffb41953cf83aac63130f4bd40 diff --git a/lib/solady b/lib/solady index fcb4426..1f43cc8 160000 --- a/lib/solady +++ b/lib/solady @@ -1 +1 @@ -Subproject commit fcb4426857d2464a316544924b20c5d43f2b0088 +Subproject commit 1f43cc8005cc3b3c8361dd7dbdd2cdeaf0f99e66 diff --git a/src/Summoner.sol b/src/Summoner.sol new file mode 100644 index 0000000..8fba5d9 --- /dev/null +++ b/src/Summoner.sol @@ -0,0 +1,45 @@ +// ᗪᗩGOᑎ 𒀭 𒀭 𒀭 𒀭 𒀭 𒀭 𒀭 𒀭 𒀭 𒀭 𒀭 +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity 0.8.26; + +/// @notice Simple summoner for Dagon (𒀭) group accounts. +/// @custom:version 1.1.1 +contract Summoner { + address internal constant DAGON = 0x000000000000FEb893BB5D63bA33323EdCC237cE; + IAccounts internal constant FACTORY = IAccounts(0x0000000000009f1E546FC4A8F68eB98031846cb8); + + struct Ownership { + address owner; + uint96 shares; + } + + enum Standard { + DAGON, + ERC20, + ERC721, + ERC1155, + ERC6909 + } + + function summon(Ownership[] calldata summoners, uint88 threshold, bool locked, bytes12 salt) public payable returns (IAccounts account) { + account = IAccounts(FACTORY.createAccount{value: msg.value}(address(this), bytes32(abi.encodePacked(this, salt)))); + for (uint256 i; i != summoners.length; ++i) + account.execute(DAGON, 0, abi.encodeWithSignature("mint(address,uint96)", summoners[i].owner, summoners[i].shares)); + if (locked) account.execute(DAGON, 0, abi.encodeWithSignature("setAuth(address)", address(0xdead))); + account.execute(DAGON, 0, abi.encodeWithSignature("setThreshold(uint88)", threshold)); + account.execute(address(account), 0, abi.encodeWithSignature("transferOwnership(address)", DAGON)); + } + + function summonForToken(address token, Standard standard, uint88 threshold, bytes12 salt) public payable returns (IAccounts account) { + account = IAccounts(FACTORY.createAccount{value: msg.value}(address(this), bytes32(abi.encodePacked(this, salt)))); + account.execute(DAGON, 0, abi.encodeWithSignature("setToken(address,uint8)", token, standard)); + account.execute(DAGON, 0, abi.encodeWithSignature("setThreshold(uint88)", threshold)); + account.execute(address(account), 0, abi.encodeWithSignature("transferOwnership(address)", DAGON)); + } +} + +/// @dev Simple interface for Nani (𒀭) user account creation and setup. +interface IAccounts { + function createAccount(address, bytes32) external payable returns (address); + function execute(address, uint256, bytes calldata) external payable returns (bytes memory); +} \ No newline at end of file