diff --git a/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/chiado-artefacts-rc-0.3.7-alpha-b824758-241007-120349.txt b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/chiado-artefacts-rc-0.3.7-alpha-b824758-241007-120349.txt new file mode 100644 index 0000000..095422f --- /dev/null +++ b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/chiado-artefacts-rc-0.3.7-alpha-b824758-241007-120349.txt @@ -0,0 +1,9 @@ +{"contractName":"Hub","deployedAddress":"0xa1d3Bc93D3b9BE137721A597796c1E7ae6598aEb","sourcePath":"src/hub/Hub.sol:Hub","constructor-args":"0xdbF22D4e8962Db3b2F1d9Ff55be728A887e47710 0x1De4cea0c6A4a67FA7Ce2Ff9c628D43D5AEA1984 0xA8366F19208FaE17f3707f5164bDC3c73eea2219 0xC7E57f5356c46b53A2A1395766B90A5d57981eDf 0x86eA22F850F7fe97De700d841200e148347Ca231 1675209600 31540000 https://gateway.aboutcircles.com/v1/circles/{id}.json","argumentsFile":"constructorArgs_Hub.txt"} +{"contractName":"Migration","deployedAddress":"0xA8366F19208FaE17f3707f5164bDC3c73eea2219","sourcePath":"src/migration/Migration.sol:Migration","constructor-args":"0xdbF22D4e8962Db3b2F1d9Ff55be728A887e47710 0xa1d3Bc93D3b9BE137721A597796c1E7ae6598aEb 1675209600","argumentsFile":"constructorArgs_Migration.txt"} +{"contractName":"NameRegistry","deployedAddress":"0x1De4cea0c6A4a67FA7Ce2Ff9c628D43D5AEA1984","sourcePath":"src/names/NameRegistry.sol:NameRegistry","constructor-args":"0xa1d3Bc93D3b9BE137721A597796c1E7ae6598aEb","argumentsFile":"constructorArgs_NameRegistry.txt"} +{"contractName":"ERC20Lift","deployedAddress":"0xC7E57f5356c46b53A2A1395766B90A5d57981eDf","sourcePath":"src/lift/ERC20Lift.sol:ERC20Lift","constructor-args":"0xa1d3Bc93D3b9BE137721A597796c1E7ae6598aEb 0x1De4cea0c6A4a67FA7Ce2Ff9c628D43D5AEA1984 0xcB42B236c3e58857A7F3D45df427535976e09027 0x0d52CBB59F817f23861b4571F1c056e7E3FaC6cE","argumentsFile":"constructorArgs_ERC20Lift.txt"} +{"contractName":"StandardTreasury","deployedAddress":"0x86eA22F850F7fe97De700d841200e148347Ca231","sourcePath":"src/treasury/StandardTreasury.sol:StandardTreasury","constructor-args":"0xa1d3Bc93D3b9BE137721A597796c1E7ae6598aEb 0x7881Eca1d73a2Da217Ac206Ae281048BdA0E1a94","argumentsFile":"constructorArgs_StandardTreasury.txt"} +{"contractName":"BaseGroupMintPolicy","deployedAddress":"0x92bfAbDc2D2608751C617e48469278CF19ef3C77","sourcePath":"src/groups/BaseMintPolicy.sol:MintPolicy","constructor-args":"","argumentsFile":"constructorArgs_BaseGroupMintPolicy.txt"} +{"contractName":"MastercopyDemurrageERC20","deployedAddress":"0xcB42B236c3e58857A7F3D45df427535976e09027","sourcePath":"src/lift/DemurrageCircles.sol:DemurrageCircles","constructor-args":"","argumentsFile":"constructorArgs_MastercopyDemurrageERC20.txt"} +{"contractName":"MastercopyInflationaryERC20","deployedAddress":"0x0d52CBB59F817f23861b4571F1c056e7E3FaC6cE","sourcePath":"src/lift/InflationaryCircles.sol:InflationaryCircles","constructor-args":"","argumentsFile":"constructorArgs_MastercopyInflationaryERC20.txt"} +{"contractName":"MastercopyStandardVault","deployedAddress":"0x7881Eca1d73a2Da217Ac206Ae281048BdA0E1a94","sourcePath":"src/treasury/StandardVault.sol:StandardVault","constructor-args":"","argumentsFile":"constructorArgs_MastercopyStandardVault.txt"} diff --git a/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/chiado-rc-0.3.7-alpha-b824758-241007-120349.log b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/chiado-rc-0.3.7-alpha-b824758-241007-120349.log new file mode 100644 index 0000000..abc87a2 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/chiado-rc-0.3.7-alpha-b824758-241007-120349.log @@ -0,0 +1,18 @@ +Chiado deployment +================= +Deployment Date: 2024-10-07 12:03:49 +Version: rc-0.3.7-alpha +Git Commit: b824758e79ab581278c0f17bd03bde7855161afc +Deployer Address: 0x7619F26728Ced663E50E578EB6ff42430931564c, Intitial nonce: 193 +Compiler Version: v0.8.23+commit.f704f362 + +Deployed Contracts: +Hub: 0xa1d3Bc93D3b9BE137721A597796c1E7ae6598aEb +Migration: 0xA8366F19208FaE17f3707f5164bDC3c73eea2219 +NameRegistry: 0x1De4cea0c6A4a67FA7Ce2Ff9c628D43D5AEA1984 +ERC20Lift: 0xC7E57f5356c46b53A2A1395766B90A5d57981eDf +StandardTreasury: 0x86eA22F850F7fe97De700d841200e148347Ca231 +BaseGroupMintPolicy: 0x92bfAbDc2D2608751C617e48469278CF19ef3C77 +MastercopyDemurrageERC20: 0xcB42B236c3e58857A7F3D45df427535976e09027 +MastercopyInflationaryERC20: 0x0d52CBB59F817f23861b4571F1c056e7E3FaC6cE +MastercopyStandardVault: 0x7881Eca1d73a2Da217Ac206Ae281048BdA0E1a94 diff --git a/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_BaseGroupMintPolicy.txt b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_BaseGroupMintPolicy.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_BaseGroupMintPolicy.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_ERC20Lift.txt b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_ERC20Lift.txt new file mode 100644 index 0000000..b5b124b --- /dev/null +++ b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_ERC20Lift.txt @@ -0,0 +1 @@ +0xa1d3Bc93D3b9BE137721A597796c1E7ae6598aEb 0x1De4cea0c6A4a67FA7Ce2Ff9c628D43D5AEA1984 0xcB42B236c3e58857A7F3D45df427535976e09027 0x0d52CBB59F817f23861b4571F1c056e7E3FaC6cE diff --git a/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_Hub.txt b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_Hub.txt new file mode 100644 index 0000000..6f01ca3 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_Hub.txt @@ -0,0 +1 @@ +0xdbF22D4e8962Db3b2F1d9Ff55be728A887e47710 0x1De4cea0c6A4a67FA7Ce2Ff9c628D43D5AEA1984 0xA8366F19208FaE17f3707f5164bDC3c73eea2219 0xC7E57f5356c46b53A2A1395766B90A5d57981eDf 0x86eA22F850F7fe97De700d841200e148347Ca231 1675209600 31540000 https://gateway.aboutcircles.com/v1/circles/{id}.json diff --git a/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_MastercopyDemurrageERC20.txt b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_MastercopyDemurrageERC20.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_MastercopyDemurrageERC20.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_MastercopyInflationaryERC20.txt b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_MastercopyInflationaryERC20.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_MastercopyInflationaryERC20.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_MastercopyStandardVault.txt b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_MastercopyStandardVault.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_MastercopyStandardVault.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_Migration.txt b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_Migration.txt new file mode 100644 index 0000000..9c81f53 --- /dev/null +++ b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_Migration.txt @@ -0,0 +1 @@ +0xdbF22D4e8962Db3b2F1d9Ff55be728A887e47710 0xa1d3Bc93D3b9BE137721A597796c1E7ae6598aEb 1675209600 diff --git a/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_NameRegistry.txt b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_NameRegistry.txt new file mode 100644 index 0000000..9157c3f --- /dev/null +++ b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_NameRegistry.txt @@ -0,0 +1 @@ +0xa1d3Bc93D3b9BE137721A597796c1E7ae6598aEb diff --git a/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_StandardTreasury.txt b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_StandardTreasury.txt new file mode 100644 index 0000000..2f805dc --- /dev/null +++ b/script/deployments/chiado-rc-0.3.7-alpha-b824758-241007-120349/constructorArgs_StandardTreasury.txt @@ -0,0 +1 @@ +0xa1d3Bc93D3b9BE137721A597796c1E7ae6598aEb 0x7881Eca1d73a2Da217Ac206Ae281048BdA0E1a94 diff --git a/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_BaseGroupMintPolicy.txt b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_BaseGroupMintPolicy.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_BaseGroupMintPolicy.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_ERC20Lift.txt b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_ERC20Lift.txt new file mode 100644 index 0000000..f735623 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_ERC20Lift.txt @@ -0,0 +1 @@ +0x3a0F7848071f067c25b0747eC5bEdc77cb3778eb 0x6192069E85afBD09D03f7e85eB6c35982A847e16 0xBF2F902d56d7ad2F2B1d674DC8B4d8C58354e7e5 0xD3529a99A7881DF7D11829135759AD0e4A8Ab587 diff --git a/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_Hub.txt b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_Hub.txt new file mode 100644 index 0000000..1629336 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_Hub.txt @@ -0,0 +1 @@ +0x29b9a7fBb8995b2423a71cC17cf9810798F6C543 0x6192069E85afBD09D03f7e85eB6c35982A847e16 0x3483cE5904413bc4Fb83DA2E43540eD769752C88 0x1CAc5fE351EFFa130223aC0f84EB6B7Efc7a66AD 0x421ae522F756412808Ff62F74C20e5ebDA8C4208 1602720000 31540000 https://gateway.aboutcircles.com/v1/circles/{id}.json diff --git a/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_MastercopyDemurrageERC20.txt b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_MastercopyDemurrageERC20.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_MastercopyDemurrageERC20.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_MastercopyInflationaryERC20.txt b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_MastercopyInflationaryERC20.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_MastercopyInflationaryERC20.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_MastercopyStandardVault.txt b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_MastercopyStandardVault.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_MastercopyStandardVault.txt @@ -0,0 +1 @@ + diff --git a/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_Migration.txt b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_Migration.txt new file mode 100644 index 0000000..887bd17 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_Migration.txt @@ -0,0 +1 @@ +0x29b9a7fBb8995b2423a71cC17cf9810798F6C543 0x3a0F7848071f067c25b0747eC5bEdc77cb3778eb 1602720000 diff --git a/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_NameRegistry.txt b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_NameRegistry.txt new file mode 100644 index 0000000..008cc9b --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_NameRegistry.txt @@ -0,0 +1 @@ +0x3a0F7848071f067c25b0747eC5bEdc77cb3778eb diff --git a/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_StandardTreasury.txt b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_StandardTreasury.txt new file mode 100644 index 0000000..85ffdf4 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/constructorArgs_StandardTreasury.txt @@ -0,0 +1 @@ +0x3a0F7848071f067c25b0747eC5bEdc77cb3778eb 0x6604C8eBDD57F3771e4D0Cb3A174AfaEAf38C463 diff --git a/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/gnosischain-artefacts-rc-0.3.7-alpha-b824758-241007-121112.txt b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/gnosischain-artefacts-rc-0.3.7-alpha-b824758-241007-121112.txt new file mode 100644 index 0000000..ce09ae9 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/gnosischain-artefacts-rc-0.3.7-alpha-b824758-241007-121112.txt @@ -0,0 +1,9 @@ +{"contractName":"Hub","deployedAddress":"0x3a0F7848071f067c25b0747eC5bEdc77cb3778eb","sourcePath":"src/hub/Hub.sol:Hub","constructor-args":"0x29b9a7fBb8995b2423a71cC17cf9810798F6C543 0x6192069E85afBD09D03f7e85eB6c35982A847e16 0x3483cE5904413bc4Fb83DA2E43540eD769752C88 0x1CAc5fE351EFFa130223aC0f84EB6B7Efc7a66AD 0x421ae522F756412808Ff62F74C20e5ebDA8C4208 1602720000 31540000 https://gateway.aboutcircles.com/v1/circles/{id}.json","argumentsFile":"constructorArgs_Hub.txt"} +{"contractName":"Migration","deployedAddress":"0x3483cE5904413bc4Fb83DA2E43540eD769752C88","sourcePath":"src/migration/Migration.sol:Migration","constructor-args":"0x29b9a7fBb8995b2423a71cC17cf9810798F6C543 0x3a0F7848071f067c25b0747eC5bEdc77cb3778eb 1602720000","argumentsFile":"constructorArgs_Migration.txt"} +{"contractName":"NameRegistry","deployedAddress":"0x6192069E85afBD09D03f7e85eB6c35982A847e16","sourcePath":"src/names/NameRegistry.sol:NameRegistry","constructor-args":"0x3a0F7848071f067c25b0747eC5bEdc77cb3778eb","argumentsFile":"constructorArgs_NameRegistry.txt"} +{"contractName":"ERC20Lift","deployedAddress":"0x1CAc5fE351EFFa130223aC0f84EB6B7Efc7a66AD","sourcePath":"src/lift/ERC20Lift.sol:ERC20Lift","constructor-args":"0x3a0F7848071f067c25b0747eC5bEdc77cb3778eb 0x6192069E85afBD09D03f7e85eB6c35982A847e16 0xBF2F902d56d7ad2F2B1d674DC8B4d8C58354e7e5 0xD3529a99A7881DF7D11829135759AD0e4A8Ab587","argumentsFile":"constructorArgs_ERC20Lift.txt"} +{"contractName":"StandardTreasury","deployedAddress":"0x421ae522F756412808Ff62F74C20e5ebDA8C4208","sourcePath":"src/treasury/StandardTreasury.sol:StandardTreasury","constructor-args":"0x3a0F7848071f067c25b0747eC5bEdc77cb3778eb 0x6604C8eBDD57F3771e4D0Cb3A174AfaEAf38C463","argumentsFile":"constructorArgs_StandardTreasury.txt"} +{"contractName":"BaseGroupMintPolicy","deployedAddress":"0x48F6B0aa3Ca905C9DbE41717c7664639107257da","sourcePath":"src/groups/BaseMintPolicy.sol:MintPolicy","constructor-args":"","argumentsFile":"constructorArgs_BaseGroupMintPolicy.txt"} +{"contractName":"MastercopyDemurrageERC20","deployedAddress":"0xBF2F902d56d7ad2F2B1d674DC8B4d8C58354e7e5","sourcePath":"src/lift/DemurrageCircles.sol:DemurrageCircles","constructor-args":"","argumentsFile":"constructorArgs_MastercopyDemurrageERC20.txt"} +{"contractName":"MastercopyInflationaryERC20","deployedAddress":"0xD3529a99A7881DF7D11829135759AD0e4A8Ab587","sourcePath":"src/lift/InflationaryCircles.sol:InflationaryCircles","constructor-args":"","argumentsFile":"constructorArgs_MastercopyInflationaryERC20.txt"} +{"contractName":"MastercopyStandardVault","deployedAddress":"0x6604C8eBDD57F3771e4D0Cb3A174AfaEAf38C463","sourcePath":"src/treasury/StandardVault.sol:StandardVault","constructor-args":"","argumentsFile":"constructorArgs_MastercopyStandardVault.txt"} diff --git a/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/gnosischain-rc-0.3.7-alpha-b824758-241007-121112.log b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/gnosischain-rc-0.3.7-alpha-b824758-241007-121112.log new file mode 100644 index 0000000..c1e6729 --- /dev/null +++ b/script/deployments/gnosischain-rc-0.3.7-alpha-b824758-241007-121112/gnosischain-rc-0.3.7-alpha-b824758-241007-121112.log @@ -0,0 +1,18 @@ +Gnosis Chain deployment +================= +Deployment Date: 2024-10-07 12:11:12 +Version: rc-0.3.7-alpha +Git Commit: b824758e79ab581278c0f17bd03bde7855161afc +Deployer Address: 0x7619F26728Ced663E50E578EB6ff42430931564c, Initial nonce: 86 +Compiler Version: v0.8.23+commit.f704f362 + +Deployed Contracts: +Hub: 0x3a0F7848071f067c25b0747eC5bEdc77cb3778eb +Migration: 0x3483cE5904413bc4Fb83DA2E43540eD769752C88 +NameRegistry: 0x6192069E85afBD09D03f7e85eB6c35982A847e16 +ERC20Lift: 0x1CAc5fE351EFFa130223aC0f84EB6B7Efc7a66AD +StandardTreasury: 0x421ae522F756412808Ff62F74C20e5ebDA8C4208 +BaseGroupMintPolicy: 0x48F6B0aa3Ca905C9DbE41717c7664639107257da +MastercopyDemurrageERC20: 0xBF2F902d56d7ad2F2B1d674DC8B4d8C58354e7e5 +MastercopyInflationaryERC20: 0xD3529a99A7881DF7D11829135759AD0e4A8Ab587 +MastercopyStandardVault: 0x6604C8eBDD57F3771e4D0Cb3A174AfaEAf38C463 diff --git a/script/deployments/package.json b/script/deployments/package.json index 1ab192d..40b01f0 100644 --- a/script/deployments/package.json +++ b/script/deployments/package.json @@ -1,6 +1,6 @@ { "name": "deploy-circles", - "version": "rc-0.3.6-alpha", + "version": "rc-0.3.7-alpha", "type": "module", "dependencies": { "dotenv": "^16.4.5", diff --git a/src/circles/Circles.sol b/src/circles/Circles.sol index 45d2c63..1b36614 100644 --- a/src/circles/Circles.sol +++ b/src/circles/Circles.sol @@ -28,12 +28,6 @@ contract Circles is ERC1155, ICirclesErrors { // Constants - /** - * @notice Issue one Circle per hour for each human in demurraged units. - * So per second issue 10**18 / 3600 = 277777777777778 attoCircles. - */ - uint256 private constant ISSUANCE_PER_SECOND = uint256(277777777777778); - /** * @notice Upon claiming, the maximum claim is upto two weeks * of history. Unclaimed older Circles are unclaimable. @@ -88,12 +82,16 @@ contract Circles is ERC1155, ICirclesErrors { MintTime memory mintTime = mintTimes[_human]; if (mintTime.mintV1Status != address(0) && mintTime.mintV1Status != CIRCLES_STOPPED_V1) { // Circles v1 contract cannot be active. - revert CirclesERC1155MintBlocked(_human, mintTime.mintV1Status); + // revert CirclesERC1155MintBlocked(_human, mintTime.mintV1Status); + revert CirclesErrorOneAddressArg(_human, 0xC0); } - if (uint256(mintTime.lastMintTime) + 1 hours > block.timestamp) { - // Mint time is set to indefinite future for stopped mints in v2 - // and only complete hours get minted, so shortcut the calculation + // Check if at least one new completed hour is mintable + uint256 lastCompletedHour = mintTime.lastMintTime / 1 hours; + uint256 currentCompletedHour = block.timestamp / 1 hours; + + if (lastCompletedHour >= currentCompletedHour || mintTime.lastMintTime == INDEFINITE_FUTURE) { + // No new completed hour to mint, or stopped return (0, 0, 0); } @@ -112,10 +110,17 @@ contract Circles is ERC1155, ICirclesErrors { // calculate the number of completed hours in day A until `startMint` int128 k = Math64x64.fromUInt((startMint - (dA * 1 days + inflationDayZero)) / 1 hours); - // Calculate the number of incompleted hours remaining in day B from current timestamp - int128 l = Math64x64.fromUInt(((dB + 1) * 1 days + inflationDayZero - block.timestamp) / 1 hours + 1); + // Calculate the number of seconds remaining in the current day (dB) + uint256 secondsRemainingInB = ((dB + 1) * 1 days + inflationDayZero - block.timestamp); + // Calculate the number of complete hours remaining + uint256 hoursRemainingInB = secondsRemainingInB / 1 hours; + // Calculate l: + // If there are any seconds beyond complete hours, add 1 to account for the incomplete hour + // Convert the result to int128 using Math64x64.fromUInt + int128 l = Math64x64.fromUInt(hoursRemainingInB + (secondsRemainingInB % 1 hours > 0 ? 1 : 0)); // calculate the overcounted (demurraged) k (in day A) and l (in day B) hours + // note that the hours l are not demurraged as it is current day by construction int128 overcount = Math64x64.add(Math64x64.mul(R[n], k), l); // subtract the overcount from the total issuance, and convert to attoCircles @@ -138,16 +143,24 @@ contract Circles is ERC1155, ICirclesErrors { // No issuance to claim, simply return without reverting return; } - // mint personal Circles to the human - _mintAndUpdateTotalSupply(_human, toTokenId(_human), issuance, ""); - // update the last mint time + + // update the last mint time, before minting as mint time determines the check (guard for reeentrancy attack) mintTimes[_human].lastMintTime = uint96(block.timestamp); + // mint personal Circles to the human; ERC1155 mint will perform acceptance call + _mintAndUpdateTotalSupply(_human, toTokenId(_human), issuance, "", true); + emit PersonalMint(_human, issuance, startPeriod, endPeriod); } - function _mintAndUpdateTotalSupply(address _account, uint256 _id, uint256 _value, bytes memory _data) internal { - _mint(_account, _id, _value, _data); + function _mintAndUpdateTotalSupply( + address _account, + uint256 _id, + uint256 _value, + bytes memory _data, + bool _doAcceptanceCheck + ) internal { + _mint(_account, _id, _value, _data, _doAcceptanceCheck); uint64 today = day(block.timestamp); DiscountedBalance memory totalSupplyBalance = discountedTotalSupplies[_id]; @@ -155,7 +168,8 @@ contract Circles is ERC1155, ICirclesErrors { _calculateDiscountedBalance(totalSupplyBalance.balance, today - totalSupplyBalance.lastUpdatedDay) + _value; if (newTotalSupply > MAX_VALUE) { // DiscountedBalances: balance exceeds maximum value - revert CirclesDemurrageAmountExceedsMaxUint190(_account, _id, newTotalSupply, 2); + // revert CirclesDemurrageAmountExceedsMaxUint192(_account, _id, newTotalSupply, 2); + revert CirclesErrorAddressUintArgs(_account, _id, 0x80); } totalSupplyBalance.balance = uint192(newTotalSupply); totalSupplyBalance.lastUpdatedDay = today; @@ -176,7 +190,8 @@ contract Circles is ERC1155, ICirclesErrors { // and the total supply might differ on the least significant bits. // There is no good way to handle this, so user should burn a few attoCRC less, // or wait a day for the total supply to be discounted to zero automatically. - revert CirclesLogicAssertion(4); + // revert CirclesLogicAssertion(4); + revert CirclesErrorNoArgs(0x84); } unchecked { totalSupplyBalance.balance = uint192(discountedTotalSupply - _value); @@ -185,14 +200,12 @@ contract Circles is ERC1155, ICirclesErrors { discountedTotalSupplies[_id] = totalSupplyBalance; } - // Private functions - /** * @dev Max function to compare two values. * @param a Value a * @param b Value b */ - function _max(uint256 a, uint256 b) private pure returns (uint256) { + function _max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } } diff --git a/src/circles/Demurrage.sol b/src/circles/Demurrage.sol index 92ed82f..3192ded 100644 --- a/src/circles/Demurrage.sol +++ b/src/circles/Demurrage.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.24; import {ABDKMath64x64 as Math64x64} from "lib/abdk-libraries-solidity/ABDKMath64x64.sol"; import "../errors/Errors.sol"; -contract Demurrage is ICirclesDemurrageErrors { +contract Demurrage is ICirclesCompactErrors, ICirclesDemurrageErrors { // Type declarations /** @@ -256,9 +256,10 @@ contract Demurrage is ICirclesDemurrageErrors { R[_dayDifference] = demurrageFactor; } return demurrageFactor; - } else { - return Math64x64.pow(GAMMA_64x64, _dayDifference); } + // if the day difference is for older than 14 days, calculate the value + // and do not cache it + return Math64x64.pow(GAMMA_64x64, _dayDifference); } /** diff --git a/src/circles/DiscountedBalances.sol b/src/circles/DiscountedBalances.sol index 5e81805..75ce835 100644 --- a/src/circles/DiscountedBalances.sol +++ b/src/circles/DiscountedBalances.sol @@ -18,6 +18,10 @@ contract DiscountedBalances is Demurrage { */ mapping(uint256 => DiscountedBalance) internal discountedTotalSupplies; + // Events + + event DiscountCost(address indexed account, uint256 indexed id, uint256 discountCost); + // Constructor /** @@ -46,7 +50,8 @@ contract DiscountedBalances is Demurrage { DiscountedBalance memory discountedBalance = discountedBalances[_id][_account]; if (_day < discountedBalance.lastUpdatedDay) { // DiscountedBalances: day is before last updated day - revert CirclesDemurrageDayBeforeLastUpdatedDay(_account, _id, _day, discountedBalance.lastUpdatedDay, 0); + // revert CirclesDemurrageDayBeforeLastUpdatedDay(_account, _id, _day, discountedBalance.lastUpdatedDay, 0); + revert CirclesErrorAddressUintArgs(_account, discountedBalance.lastUpdatedDay, 0xA0); } uint256 dayDifference; unchecked { @@ -93,7 +98,8 @@ contract DiscountedBalances is Demurrage { function _updateBalance(address _account, uint256 _id, uint256 _balance, uint64 _day) internal { if (_balance > MAX_VALUE) { // DiscountedBalances: balance exceeds maximum value - revert CirclesDemurrageAmountExceedsMaxUint190(_account, _id, _balance, 0); + // revert CirclesDemurrageAmountExceedsMaxUint192(_account, _id, _balance, 0); + revert CirclesErrorAddressUintArgs(_account, _id, 0x81); } DiscountedBalance memory discountedBalance = discountedBalances[_id][_account]; discountedBalance.balance = uint192(_balance); @@ -112,7 +118,8 @@ contract DiscountedBalances is Demurrage { DiscountedBalance memory discountedBalance = discountedBalances[_id][_account]; if (_day < discountedBalance.lastUpdatedDay) { // DiscountedBalances: day is before last updated day - revert CirclesDemurrageDayBeforeLastUpdatedDay(_account, _id, _day, discountedBalance.lastUpdatedDay, 1); + // revert CirclesDemurrageDayBeforeLastUpdatedDay(_account, _id, _day, discountedBalance.lastUpdatedDay, 1); + revert CirclesErrorAddressUintArgs(_account, discountedBalance.lastUpdatedDay, 0xA1); } uint256 dayDifference; unchecked { @@ -124,12 +131,14 @@ contract DiscountedBalances is Demurrage { uint256 discountCost = discountedBalance.balance - discountedBalanceOnDay; if (discountCost > 0) { emit IERC1155.TransferSingle(msg.sender, _account, address(0), _id, discountCost); + emit DiscountCost(_account, _id, discountCost); } } uint256 updatedBalance = discountedBalanceOnDay + _value; if (updatedBalance > MAX_VALUE) { // DiscountedBalances: balance exceeds maximum value - revert CirclesDemurrageAmountExceedsMaxUint190(_account, _id, updatedBalance, 1); + // revert CirclesDemurrageAmountExceedsMaxUint190(_account, _id, updatedBalance, 1); + revert CirclesErrorAddressUintArgs(_account, _id, 0x82); } discountedBalance.balance = uint192(updatedBalance); discountedBalance.lastUpdatedDay = _day; diff --git a/src/circles/ERC1155.sol b/src/circles/ERC1155.sol index 8ad5f21..b0a2dba 100644 --- a/src/circles/ERC1155.sol +++ b/src/circles/ERC1155.sol @@ -174,6 +174,7 @@ abstract contract ERC1155 is DiscountedBalances, Context, ERC165, IERC1155, IERC } if (discountCost > 0) { emit TransferSingle(operator, from, address(0), id, discountCost); + emit DiscountCost(from, id, discountCost); } unchecked { // Overflow not possible: value <= fromBalance @@ -318,15 +319,20 @@ abstract contract ERC1155 is DiscountedBalances, Context, ERC165, IERC1155, IERC * Requirements: * * - `to` cannot be the zero address. + * - If `_doAcceptanceCheck` is true, it will perform ERC1155 acceptance check, otherwise only update * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ - function _mint(address to, uint256 id, uint256 value, bytes memory data) internal { + function _mint(address to, uint256 id, uint256 value, bytes memory data, bool _doAcceptanceCheck) internal { if (to == address(0)) { revert ERC1155InvalidReceiver(address(0)); } (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value); - _updateWithAcceptanceCheck(address(0), to, ids, values, data); + if (_doAcceptanceCheck) { + _updateWithAcceptanceCheck(address(0), to, ids, values, data); + } else { + _update(address(0), to, ids, values); + } } /** diff --git a/src/circles/InflationaryOperator.sol b/src/circles/InflationaryOperator.sol index 1105940..20f542b 100644 --- a/src/circles/InflationaryOperator.sol +++ b/src/circles/InflationaryOperator.sol @@ -27,6 +27,8 @@ contract InflationaryCirclesOperator is BatchedDemurrage { constructor(IHubV2 _hub) { hub = _hub; + // read inflation day zero from hub + inflationDayZero = hub.inflationDayZero(); } // Public functions diff --git a/src/errors/Errors.sol b/src/errors/Errors.sol index 155d4d0..ce5ef4c 100644 --- a/src/errors/Errors.sol +++ b/src/errors/Errors.sol @@ -1,72 +1,159 @@ // SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.24; +// Explainer on error codes: 3 leading bits for the error type, 5 bits for the error code. +// +------------+-------------------+-------------+ +// | Error Type | Hex Code Range | Occurances | +// +------------+-------------------+-------------+ +// | 0 | 0x00 to 0x1F | 32 | +// | 1 | 0x20 to 0x3F | 32 | +// | 2 | 0x40 to 0x5F | 32 | +// | 3 | 0x60 to 0x7F | 32 | +// | 4 | 0x80 to 0x9F | 32 | +// | 5 | 0xA0 to 0xBF | 32 | +// | 6 | 0xC0 to 0xDF | 32 | +// | 7 | 0xE0 to 0xFF | 32 | +// +------------+-------------------+-------------+ +// +// for convenience a reference table for the 32 occurances hex conversions; +// so you can "add" the error type easily +// +------------+------------+------------+------------+------------+------------+------------+------------+ +// | Occurrence | Hex Code | Occurrence | Hex Code | Occurrence | Hex Code | Occurrence | Hex Code | +// +------------+------------+------------+------------+------------+------------+------------+------------+ +// | 0 | 0x00 | 1 | 0x01 | 2 | 0x02 | 3 | 0x03 | +// | 4 | 0x04 | 5 | 0x05 | 6 | 0x06 | 7 | 0x07 | +// | 8 | 0x08 | 9 | 0x09 | 10 | 0x0A | 11 | 0x0B | +// | 12 | 0x0C | 13 | 0x0D | 14 | 0x0E | 15 | 0x0F | +// | 16 | 0x10 | 17 | 0x11 | 18 | 0x12 | 19 | 0x13 | +// | 20 | 0x14 | 21 | 0x15 | 22 | 0x16 | 23 | 0x17 | +// | 24 | 0x18 | 25 | 0x19 | 26 | 0x1A | 27 | 0x1B | +// | 28 | 0x1C | 29 | 0x1D | 30 | 0x1E | 31 | 0x1F | +// +------------+------------+------------+------------+------------+------------+------------+------------+ + +interface ICirclesCompactErrors { + /** + * @dev CirclesErrorNoArgs is a generic error that does not require any arguments. + * error type: + * 0: 0x00 -> 0x1F CirclesAddressCannotBeZero + * 1: 0x20 -> 0x3F CirclesArrayMustNotBeEmpty (no occurances anymore; freed up) + * 2: 0x40 -> 0x5F CirclesAmountMustNotBeZero + * 3: 0x60 -> 0x7F CirclesHubFlowVerticesMustBeSorted + * 4: 0x80 -> 0x9F CirclesLogicAssertion + * 5: 0xA0 -> 0xBF CirclesArraysLengthMismatch + */ + error CirclesErrorNoArgs(uint8); + + /** + * @dev CirclesErrorOneAddressArg is a generic error that requires one address argument. + * error type: + * 0: 0x00 -> 0x1F CirclesHubMustBeHuman(avatar) + * 1: 0x20 -> 0x3F CirclesAvatarMustBeRegistered(avatar) + * 2: 0x40 -> 0x5F CirclesHubGroupIsNotRegistered(group) + * 3: 0x60 -> 0x7F CirclesHubRegisterAvatarV1MustBeStoppedBeforeEndOfInvitationPeriod(avatar) + * 4: 0x80 -> 0x9F CirclesHubAvatarAlreadyRegistered(avatar) + * 5: 0xA0 -> 0xBF CirclesHubInvalidTrustReceiver(trustReceiver) + * 6: 0xC0 -> 0xDF CirclesERC1155MintBlocked(human, ~mintV1Status~) + * 7: 0xE0 -> 0xFF CirclesInvalidFunctionCaller(caller) + */ + error CirclesErrorOneAddressArg(address, uint8); + + /** + * @dev CirclesErrorAddressUintArgs is a generic error that provides an address and a uint256 as arguments. + * error type: + * 0: 0x00 -> 0x1F CirclesHubOperatorNotApprovedForSource(source, streamIndex) + * 1: 0x20 -> 0x3F CirclesHubFlowEdgeIsNotPermitted(receiver, circlesId) + * 2: 0x40 -> 0x5F CirclesHubGroupMintPolicyRejectedBurn(burner, toTokenId(group)) + * 3: 0x60 -> 0x7F CirclesHubGroupMintPolicyRejectedMint(minter, toTokenId) + * 4: 0x80 -> 0x9F CirclesDemurrageAmountExceedsMaxUint192(account, circlesId) + * 5: 0xA0 -> 0xBF CirclesDemurrageDayBeforeLastUpdatedDay(account, lastDayUpdated) + */ + error CirclesErrorAddressUintArgs(address, uint256, uint8); +} + interface IHubErrors { - error CirclesHubRegisterAvatarV1MustBeStoppedBeforeEndOfInvitationPeriod(address avatar, uint8 code); + // CirclesErrorOneAddressArg 3 + // error CirclesHubRegisterAvatarV1MustBeStoppedBeforeEndOfInvitationPeriod(address avatar, uint8 code); - error CirclesHubAvatarAlreadyRegistered(address avatar, uint8 code); + // CirclesErrorOneAddressArg 4 + // error CirclesHubAvatarAlreadyRegistered(address avatar, uint8 code); - error CirclesHubMustBeHuman(address avatar, uint8 code); + // CirclesErrorOneAddressArg 0 + // error CirclesHubMustBeHuman(address avatar, uint8 code); - error CirclesHubGroupIsNotRegistered(address group, uint8 code); + // CirclesErrorOneAddressArg 2 + // error CirclesHubGroupIsNotRegistered(address group, uint8 code); - error CirclesHubInvalidTrustReceiver(address trustReceiver, uint8 code); + // CirclesErrorOneAddressArg 5 + // error CirclesHubInvalidTrustReceiver(address trustReceiver, uint8 code); - error CirclesHubGroupMintPolicyRejectedMint( - address minter, address group, uint256[] collateral, uint256[] amounts, bytes data, uint8 code - ); + // CirclesErrorAddressUintArgs 3 + // error CirclesHubGroupMintPolicyRejectedMint( + // address minter, address group, uint256[] collateral, uint256[] amounts, bytes data, uint8 code + // ); - error CirclesHubGroupMintPolicyRejectedBurn(address burner, address group, uint256 amount, bytes data, uint8 code); + // CirclesErrorAddressUintArgs 2 + // error CirclesHubGroupMintPolicyRejectedBurn(address burner, address group, uint256 amount, bytes data, uint8 code); - error CirclesHubOperatorNotApprovedForSource(address operator, address source, uint16 streamId, uint8 code); + // CirclesErrorAddressUintArgs 0 + // error CirclesHubOperatorNotApprovedForSource(address operator, address source, uint16 streamIndex, uint8 code); - error CirclesHubFlowEdgeIsNotPermitted(address receiver, uint256 circlesId, uint8 code); + // CirclesErrorAddressUintArgs 1 + // error CirclesHubFlowEdgeIsNotPermitted(address receiver, uint256 circlesId, uint8 code); - error CirclesHubFlowVerticesMustBeSorted(); + // CirclesErrorNoArgs 3 + // error CirclesHubFlowVerticesMustBeSorted(); error CirclesHubFlowEdgeStreamMismatch(uint16 flowEdgeId, uint16 streamId, uint8 code); - error CirclesHubStreamMismatch(uint16 streamId, uint8 code); + error CirclesHubStreamMismatch(uint16 streamId); error CirclesHubNettedFlowMismatch(uint16 vertexPosition, int256 matrixNettedFlow, int256 streamNettedFlow); } interface ICirclesDemurrageErrors { - error CirclesERC1155MintBlocked(address human, address mintV1Status); + // CirclesErrorOneAddressArg 6 + // error CirclesERC1155MintBlocked(address human, address mintV1Status); - error CirclesDemurrageAmountExceedsMaxUint190(address account, uint256 circlesId, uint256 amount, uint8 code); + // CirclesErrorAddressUintArgs 4 + // error CirclesDemurrageAmountExceedsMaxUint192(address account, uint256 circlesId, uint256 amount, uint8 code); - error CirclesDemurrageDayBeforeLastUpdatedDay( - address account, uint256 circlesId, uint64 day, uint64 lastUpdatedDay, uint8 code - ); + // CirclesErrorAddressUintArgs 5 + // error CirclesDemurrageDayBeforeLastUpdatedDay( + // address account, uint256 circlesId, uint64 day, uint64 lastUpdatedDay, uint8 code + // ); error CirclesERC1155CannotReceiveBatch(uint8 code); } interface ICirclesErrors { - error CirclesAvatarMustBeRegistered(address avatar, uint8 code); + // CirclesErrorOneAddressArg 1 + // error CirclesAvatarMustBeRegistered(address avatar, uint8 code); - error CirclesAddressCannotBeZero(uint8 code); + // CirclesErrorNoArgs 0 + // error CirclesAddressCannotBeZero(uint8 code); - error CirclesInvalidFunctionCaller(address caller, address expectedCaller, uint8 code); + // CirclesErrorOneAddressArg + // error CirclesInvalidFunctionCaller(address caller, address expectedCaller, uint8 code); error CirclesInvalidCirclesId(uint256 id, uint8 code); - error CirclesInvalidString(string str, uint8 code); - error CirclesInvalidParameter(uint256 parameter, uint8 code); error CirclesAmountOverflow(uint256 amount, uint8 code); - error CirclesArraysLengthMismatch(uint256 lengthArray1, uint256 lengthArray2, uint8 code); + // CirclesErrorNoArgs 5 + // error CirclesArraysLengthMismatch(uint256 lengthArray1, uint256 lengthArray2, uint8 code); - error CirclesArrayMustNotBeEmpty(uint8 code); + // CirclesErrorNoArgs 1 + // error CirclesArrayMustNotBeEmpty(uint8 code); - error CirclesAmountMustNotBeZero(uint8 code); + // CirclesErrorNoArgs 2 + // error CirclesAmountMustNotBeZero(uint8 code); error CirclesProxyAlreadyInitialized(); - error CirclesLogicAssertion(uint8 code); + // CirclesErrorNoArgs 4 + // error CirclesLogicAssertion(uint8 code); error CirclesIdMustBeDerivedFromAddress(uint256 providedId, uint8 code); @@ -95,4 +182,10 @@ interface INameRegistryErrors { error CirclesNamesAvatarAlreadyHasCustomNameOrSymbol(address avatar, string nameOrSymbol, uint8 code); error CirclesNamesOrganizationHasNoSymbol(address organization, uint8 code); + + error CirclesNamesShortNameZero(address avatar, uint256 nonce); +} + +interface IMigrationErrors { + error CirclesMigrationAmountMustBeGreaterThanZero(); } diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index b99a4a9..da4c524 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -25,12 +25,12 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // Constants /** - * @dev Welcome bonus for new avatars invited to Circles. Set to 50 Circles. + * @dev Welcome bonus for new avatars invited to Circles. Set to 48 Circles. */ uint256 private constant WELCOME_BONUS = 48 * EXA; /** - * @dev The cost of an invitation for a new avatar, paid in personal Circles burnt, set to 100 Circles. + * @dev The cost of an invitation for a new avatar, paid in personal Circles burnt, set to 96 Circles. */ uint256 private constant INVITATION_COST = 2 * WELCOME_BONUS; @@ -113,7 +113,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // Events - event RegisterHuman(address indexed avatar); + event RegisterHuman(address indexed avatar, address indexed inviter); event RegisterOrganization(address indexed organization, string name); event RegisterGroup( address indexed group, address indexed mint, address indexed treasury, string name, string symbol @@ -123,10 +123,18 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { event Stopped(address indexed avatar); + event FlowEdgesScopeSingleStarted(uint256 indexed flowEdgeId, uint16 streamId); + event FlowEdgesScopeLastEnded(); event StreamCompleted( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] amounts ); + event GroupMint( + address indexed sender, address indexed receiver, address indexed group, uint256[] collateral, uint256[] amounts + ); + + event SetAdvancedUsageFlag(address indexed avatar, bytes32 flag); + // Modifiers /** @@ -134,7 +142,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { */ modifier onlyMigration() { if (msg.sender != migration) { - revert CirclesInvalidFunctionCaller(msg.sender, migration, 0); + // revert CirclesInvalidFunctionCaller(msg.sender, migration, 0); + revert CirclesErrorOneAddressArg(msg.sender, 0xE0); } _; } @@ -143,7 +152,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { * @dev Reentrancy guard for nonReentrant functions. * see https://soliditylang.org/blog/2024/01/26/transient-storage/ */ - modifier nonReentrant(uint8 _code) { + modifier nonReentrant() { assembly { if tload(0) { revert(0, 0) } tstore(0, 1) @@ -178,10 +187,12 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { string memory _gatewayUrl ) Circles(_inflationDayZero, _gatewayUrl) { if (address(_hubV1) == address(0)) { - revert CirclesAddressCannotBeZero(0); + // revert CirclesAddressCannotBeZero(0); + revert CirclesErrorNoArgs(0x00); } if (_standardTreasury == address(0)) { - revert CirclesAddressCannotBeZero(1); + // revert CirclesAddressCannotBeZero(1); + revert CirclesErrorNoArgs(0x01); } // initialize linked list for avatars @@ -228,39 +239,35 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // leave the inviter address as zero. // only available for v1 users with stopped v1 mint, for initial bootstrap period - (address v1CirclesStatus, uint256 v1LastTouched) = _registerHuman(msg.sender); + (address v1CirclesStatus, uint256 v1LastTouched) = _registerHuman(msg.sender, _inviter); // check if v1 Circles exists and has been stopped - if (v1CirclesStatus != CIRCLES_STOPPED_V1) { - revert CirclesHubRegisterAvatarV1MustBeStoppedBeforeEndOfInvitationPeriod(msg.sender, 0); - } - // if it has been stopped, did it stop before the end of the invitation period? - if (v1LastTouched >= invitationOnlyTime) { - revert CirclesHubRegisterAvatarV1MustBeStoppedBeforeEndOfInvitationPeriod(msg.sender, 1); + // and if it has been stopped, did it stop before the end of the invitation period? + if (v1CirclesStatus != CIRCLES_STOPPED_V1 || v1LastTouched >= invitationOnlyTime) { + // revert CirclesHubRegisterAvatarV1MustBeStoppedBeforeEndOfInvitationPeriod(msg.sender, 0); + revert CirclesErrorOneAddressArg(msg.sender, 0x60); } } else { // if someone has invited you by trusting your address ahead of this call, // they must themselves be a registered human, and they must pay the invitation cost (after invitation period). - if (!isHuman(_inviter)) { - revert CirclesHubMustBeHuman(msg.sender, 0); - } - - if (!isTrusted(_inviter, msg.sender)) { - revert CirclesHubInvalidTrustReceiver(msg.sender, 0); + if (!isHuman(_inviter) || !isTrusted(_inviter, msg.sender)) { + // revert CirclesHubMustBeHuman(msg.sender, 0); + // revert CirclesHubInvalidTrustReceiver(msg.sender, 0); + revert CirclesErrorOneAddressArg(_inviter, 0xA0); } // register the invited human; reverts if they already exist // it checks the status of the avatar in v1, but regardless of the status // we can proceed to register the avatar in v2 (they might not be able to mint yet // if they have not stopped their v1 contract) - _registerHuman(msg.sender); + _registerHuman(msg.sender, _inviter); if (block.timestamp > invitationOnlyTime) { // after the invitation period, the inviter must burn the invitation cost _burnAndUpdateTotalSupply(_inviter, toTokenId(_inviter), INVITATION_COST); // mint the welcome bonus to the newly registered human - _mintAndUpdateTotalSupply(msg.sender, toTokenId(msg.sender), WELCOME_BONUS, ""); + _mintAndUpdateTotalSupply(msg.sender, toTokenId(msg.sender), WELCOME_BONUS, "", true); } } @@ -346,18 +353,17 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { * The trusted address does not (yet) have to be registered in the Hub contract. */ function trust(address _trustReceiver, uint96 _expiry) external { - if (avatars[msg.sender] == address(0)) { - revert CirclesAvatarMustBeRegistered(msg.sender, 0); - } - if (_trustReceiver == address(0) || _trustReceiver == SENTINEL) { + if ( + avatars[msg.sender] == address(0) || _trustReceiver == address(0) || _trustReceiver == SENTINEL + || _trustReceiver == msg.sender + ) { // You cannot trust the zero address or the sentinel address. // Reserved addresses for logic. - revert CirclesHubInvalidTrustReceiver(_trustReceiver, 1); - } - if (_trustReceiver == msg.sender) { - // You cannot edit your own trust relation. - revert CirclesHubInvalidTrustReceiver(_trustReceiver, 2); + // You also cannot edit your own trust relation. + // revert CirclesHubInvalidTrustReceiver(_trustReceiver, 1); + revert CirclesErrorOneAddressArg(_trustReceiver, 0xA1); } + // expiring trust cannot be set in the past if (_expiry < block.timestamp) _expiry = uint96(block.timestamp); _trust(msg.sender, _trustReceiver, _expiry); @@ -369,7 +375,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { function personalMint() external { if (!isHuman(msg.sender)) { // Only avatars registered as human can call personal mint. - revert CirclesHubMustBeHuman(msg.sender, 1); + // revert CirclesHubMustBeHuman(msg.sender, 1); + revert CirclesErrorOneAddressArg(msg.sender, 0x01); } // check if v1 Circles is known to be stopped and update status _checkHumanV1CirclesStatus(msg.sender); @@ -436,7 +443,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { function stop() external { if (!isHuman(msg.sender)) { // Only human can call stop. - revert CirclesHubMustBeHuman(msg.sender, 2); + // revert CirclesHubMustBeHuman(msg.sender, 2); + revert CirclesErrorOneAddressArg(msg.sender, 0x02); } MintTime storage mintTime = mintTimes[msg.sender]; // check if already stopped @@ -457,7 +465,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { function stopped(address _human) external view returns (bool) { if (!isHuman(_human)) { // Only personal Circles can have a status of boolean stopped. - revert CirclesHubMustBeHuman(_human, 3); + // revert CirclesHubMustBeHuman(_human, 3); + revert CirclesErrorOneAddressArg(_human, 0x03); } MintTime storage mintTime = mintTimes[msg.sender]; return (mintTime.lastMintTime == INDEFINITE_FUTURE); @@ -475,31 +484,32 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { * @param _amounts array of amounts in inflationary v1 units to migrate */ function migrate(address _owner, address[] calldata _avatars, uint256[] calldata _amounts) external onlyMigration { - if (avatars[_owner] == address(0)) { + if (avatars[_owner] == address(0) || _avatars.length != _amounts.length) { // Only registered avatars can migrate v1 tokens. - revert CirclesAvatarMustBeRegistered(_owner, 1); - } - if (_avatars.length != _amounts.length) { - revert CirclesArraysLengthMismatch(_avatars.length, _amounts.length, 0); + // Array length is already checked in the migration contract, so redundant check here, + // can be collapsed under the more meaningful error. + // revert CirclesAvatarMustBeRegistered(_owner, 1); + revert CirclesErrorOneAddressArg(_owner, 0x21); } // register all unregistered avatars as humans, and check that registered avatars are humans // after the bootstrap period, the _owner needs to pay the equivalent invitation cost for all newly registered humans - uint256 cost = INVITATION_COST * _ensureAvatarsRegistered(_avatars); + uint256 cost = INVITATION_COST * _ensureAvatarsRegistered(_owner, _avatars); // Invitation cost only applies after the bootstrap period if (block.timestamp > invitationOnlyTime && cost > 0) { // personal Circles are required to burn the invitation cost if (!isHuman(_owner)) { // Only humans can migrate v1 tokens after the bootstrap period. - revert CirclesHubMustBeHuman(_owner, 4); + // revert CirclesHubMustBeHuman(_owner, 4); + revert CirclesErrorOneAddressArg(_owner, 0x04); } _burnAndUpdateTotalSupply(_owner, toTokenId(_owner), cost); } for (uint256 i = 0; i < _avatars.length; i++) { // mint the migrated balances to _owner - _mintAndUpdateTotalSupply(_owner, toTokenId(_avatars[i]), _amounts[i], ""); + _mintAndUpdateTotalSupply(_owner, toTokenId(_avatars[i]), _amounts[i], "", true); } } @@ -521,7 +531,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // then the mint policy must approve the burn if (!policy.beforeBurnPolicy(msg.sender, group, _amount, _data)) { // Burn policy rejected burn. - revert CirclesHubGroupMintPolicyRejectedBurn(msg.sender, group, _amount, _data, 0); + // revert CirclesHubGroupMintPolicyRejectedBurn(msg.sender, group, _amount, _data, 0); + revert CirclesErrorAddressUintArgs(msg.sender, _id, 0x40); } } _burnAndUpdateTotalSupply(msg.sender, _id, _amount); @@ -530,7 +541,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { function wrap(address _avatar, uint256 _amount, CirclesType _type) external returns (address) { if (!isHuman(_avatar) && !isGroup(_avatar)) { // Avatar must be human or group. - revert CirclesAvatarMustBeRegistered(_avatar, 2); + // revert CirclesAvatarMustBeRegistered(_avatar, 2); + revert CirclesErrorOneAddressArg(_avatar, 0x22); } address erc20Wrapper = liftERC20.ensureERC20(_avatar, _type); safeTransferFrom(msg.sender, erc20Wrapper, toTokenId(_avatar), _amount, ""); @@ -543,7 +555,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { FlowEdge[] calldata _flow, Stream[] calldata _streams, bytes calldata _packedCoordinates - ) external nonReentrant(0) { + ) external nonReentrant { // first unpack the coordinates to array of uint16 uint16[] memory coordinates = _unpackCoordinates(_packedCoordinates, _flow.length); @@ -551,9 +563,10 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { for (uint16 i = 0; i < _streams.length; i++) { if (!isApprovedForAll(_flowVertices[_streams[i].sourceCoordinate], msg.sender)) { // Operator not approved for source. - revert CirclesHubOperatorNotApprovedForSource( - msg.sender, _flowVertices[_streams[i].sourceCoordinate], i, 0 - ); + // revert CirclesHubOperatorNotApprovedForSource( + // msg.sender, _flowVertices[_streams[i].sourceCoordinate], i, 0 + // ); + revert CirclesErrorAddressUintArgs(_flowVertices[_streams[i].sourceCoordinate], i, 0x00); } } @@ -580,10 +593,14 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { function setAdvancedUsageFlag(bytes32 _flag) external { if (avatars[msg.sender] == address(0)) { // Only registered avatars can set advanced usage flags. - revert CirclesAvatarMustBeRegistered(msg.sender, 3); + // revert CirclesAvatarMustBeRegistered(msg.sender, 3); + revert CirclesErrorOneAddressArg(msg.sender, 0x23); } advancedUsageFlags[msg.sender] = _flag; + + // emit event for setting the advanced usage flag + emit SetAdvancedUsageFlag(msg.sender, _flag); } // Public functions @@ -673,17 +690,16 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { bytes memory _data, bool _explicitCall ) internal { - if (_collateral.length != _amounts.length) { + if (_collateral.length != _amounts.length || _collateral.length == 0) { // Collateral and amount arrays must have equal length. - revert CirclesArraysLengthMismatch(_collateral.length, _amounts.length, 1); - } - if (_collateral.length == 0) { // At least one collateral must be provided. - revert CirclesArrayMustNotBeEmpty(0); + // revert CirclesArraysLengthMismatch(_collateral.length, _amounts.length, 1); + revert CirclesErrorNoArgs(0xA1); } if (!isGroup(_group)) { // Group is not registered as an avatar. - revert CirclesHubGroupIsNotRegistered(_group, 0); + // revert CirclesHubGroupIsNotRegistered(_group, 0); + revert CirclesErrorOneAddressArg(_group, 0x40); } // note: we don't need to check whether collateral circle ids are registered, @@ -698,22 +714,21 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { bool isValidCollateral = _explicitCall ? isTrusted(_group, collateralAvatar) : isPermittedFlow(_sender, _group, collateralAvatar); - if (!isValidCollateral) { + if (!isValidCollateral || _amounts[i] == 0) { // Group does not trust collateral, or flow edge is not permitted - revert CirclesHubFlowEdgeIsNotPermitted(_group, _collateral[i], 0); - } - - if (_amounts[i] == 0) { // Non-zero collateral must be provided. - revert CirclesAmountMustNotBeZero(0); + // revert CirclesHubFlowEdgeIsNotPermitted(_group, _collateral[i], 0); + revert CirclesErrorAddressUintArgs(_group, _collateral[i], 0x20); } + sumAmounts += _amounts[i]; } // Rely on the mint policy to determine whether the collateral is valid for minting if (!IMintPolicy(mintPolicies[_group]).beforeMintPolicy(_sender, _group, _collateral, _amounts, _data)) { // Mint policy rejected mint. - revert CirclesHubGroupMintPolicyRejectedMint(_sender, _group, _collateral, _amounts, _data, 0); + // revert CirclesHubGroupMintPolicyRejectedMint(_sender, _group, _collateral, _amounts, _data, 0); + revert CirclesErrorAddressUintArgs(_sender, toTokenId(_group), 0x60); } // abi encode the group address into the data to send onwards to the treasury @@ -725,8 +740,13 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // note: treasury.on1155Received must implement and unpack the GroupMintMetadata to know the group safeBatchTransferFrom(_sender, treasuries[_group], _collateral, _amounts, dataWithGroup); - // mint group Circles to the receiver and send the original _data onwards - _mintAndUpdateTotalSupply(_receiver, toTokenId(_group), sumAmounts, _data); + // mint group Circles to the receiver and send the original _data onwards. + // Only if it is an explicit call perform the ERC1155 acceptance call; if not (ie via path), + // suppress the normal acceptance call and only perform the final stream based acceptance calls + _mintAndUpdateTotalSupply(_receiver, toTokenId(_group), sumAmounts, _data, _explicitCall); + + // emit the group mint event + emit GroupMint(_sender, _receiver, _group, _collateral, _amounts); } /** @@ -743,17 +763,13 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { FlowEdge[] calldata _flow, uint16[] memory _coordinates ) internal view returns (int256[] memory) { - if (3 * _flow.length != _coordinates.length) { - // Mismatch in flow and coordinates length. - revert CirclesArraysLengthMismatch(_flow.length, _coordinates.length, 2); - } - if (_flowVertices.length > type(uint16).max) { - // Too many vertices. - revert CirclesArraysLengthMismatch(_flowVertices.length, type(uint16).max, 3); - } - if (_flowVertices.length == 0 || _flow.length == 0) { - // Empty flow matrix - revert CirclesArraysLengthMismatch(_flowVertices.length, _flow.length, 4); + if ( + 3 * _flow.length != _coordinates.length // Mismatch in flow and coordinates length. + || _flowVertices.length > type(uint16).max // Too many vertices. + || _flowVertices.length == 0 || _flow.length == 0 // Empty flow matrix + ) { + // revert CirclesArraysLengthMismatch(_flow.length, _coordinates.length, 2); + revert CirclesErrorNoArgs(0xA2); } // initialize the netted flow array @@ -764,18 +780,21 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { for (uint64 i = 0; i < _flowVertices.length - 1; i++) { if (uint160(_flowVertices[i]) >= uint160(_flowVertices[i + 1])) { // Flow vertices must be in ascending order. - revert CirclesHubFlowVerticesMustBeSorted(); + // revert CirclesHubFlowVerticesMustBeSorted(); + revert CirclesErrorNoArgs(0x60); } if (avatars[_flowVertices[i]] == address(0)) { // Avatar must be registered. - revert CirclesAvatarMustBeRegistered(_flowVertices[i], 4); + // revert CirclesAvatarMustBeRegistered(_flowVertices[i], 4); + revert CirclesErrorOneAddressArg(_flowVertices[i], 0x24); } } address lastAvatar = _flowVertices[_flowVertices.length - 1]; if (avatars[lastAvatar] == address(0)) { // Avatar must be registered. - revert CirclesAvatarMustBeRegistered(lastAvatar, 5); + // revert CirclesAvatarMustBeRegistered(lastAvatar, 5); + revert CirclesErrorOneAddressArg(lastAvatar, 0x25); } } @@ -796,7 +815,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // and if the sender has enabled consented flow, also check that the sender trusts the receiver if (!isPermittedFlow(from, to, circlesId)) { // Flow edge is not permitted. - revert CirclesHubFlowEdgeIsNotPermitted(to, toTokenId(circlesId), 1); + // revert CirclesHubFlowEdgeIsNotPermitted(to, toTokenId(circlesId), 1); + revert CirclesErrorAddressUintArgs(to, toTokenId(circlesId), 0x21); } // nett the flow, dividing out the different Circle identifiers @@ -853,14 +873,14 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { streamBatchCounter[streamSinkArrayId]++; if (streamReceivers[streamSinkArrayId] == address(0)) { streamReceivers[streamSinkArrayId] = to; - } else { - if (streamReceivers[streamSinkArrayId] != to) { - // Invalid stream receiver - revert CirclesHubFlowEdgeStreamMismatch(i, _flow[i].streamSinkId, 1); - } + } else if (streamReceivers[streamSinkArrayId] != to) { + // Invalid stream receiver + revert CirclesHubFlowEdgeStreamMismatch(i, _flow[i].streamSinkId, 1); } } + emit FlowEdgesScopeSingleStarted(i, _flow[i].streamSinkId); + // effect the flow edge if (!isGroup(to)) { // do a erc1155 single transfer without acceptance check, @@ -887,15 +907,13 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { index = index + 3; } + emit FlowEdgesScopeLastEnded(); + // check that all streams are properly defined for (uint16 i = 0; i < _streams.length; i++) { - if (streamReceivers[i] == address(0)) { + if (streamReceivers[i] == address(0) || streamBatchCounter[i] != _streams[i].flowEdgeIds.length) { // Invalid stream receiver - revert CirclesHubStreamMismatch(i, 0); - } - if (streamBatchCounter[i] != _streams[i].flowEdgeIds.length) { - // Invalid stream batch - revert CirclesHubStreamMismatch(i, 1); + revert CirclesHubStreamMismatch(i); } } } @@ -954,12 +972,13 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { function _matchNettedFlows(int256[] memory _streamsNettedFlow, int256[] memory _matrixNettedFlow) internal pure { if (_streamsNettedFlow.length != _matrixNettedFlow.length) { // Mismatch in netted flow length. - revert CirclesArraysLengthMismatch(_streamsNettedFlow.length, _matrixNettedFlow.length, 5); + // revert CirclesArraysLengthMismatch(_streamsNettedFlow.length, _matrixNettedFlow.length, 5); + revert CirclesErrorNoArgs(0xA5); } for (uint16 i = 0; i < _streamsNettedFlow.length; i++) { if (_streamsNettedFlow[i] != _matrixNettedFlow[i]) { // Intended flow does not match verified flow. - revert CirclesHubNettedFlowMismatch(i, _streamsNettedFlow[i], _matrixNettedFlow[i]); + revert CirclesHubNettedFlowMismatch(i, _matrixNettedFlow[i], _streamsNettedFlow[i]); } } } @@ -970,7 +989,10 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { * Additionally set the trust to self indefinitely. * @param _human address of the human to be registered */ - function _registerHuman(address _human) internal returns (address v1CirclesStatus, uint256 v1LastTouched) { + function _registerHuman(address _human, address _inviter) + internal + returns (address v1CirclesStatus, uint256 v1LastTouched) + { // insert avatar into linked list; reverts if it already exists _insertAvatar(_human); @@ -984,7 +1006,7 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // trust self indefinitely, cannot be altered later _trust(_human, _human, INDEFINITE_FUTURE); - emit RegisterHuman(_human); + emit RegisterHuman(_human, _inviter); return (v1CirclesStatus, v1LastTouched); } @@ -1004,25 +1026,15 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { string calldata _name, string calldata _symbol ) internal { - // todo: we could check ERC165 support interface for mint policy - if (_mint == address(0)) { + if (_mint == address(0) || _treasury == address(0)) { // Mint address can not be zero. - revert CirclesAddressCannotBeZero(2); - } - // todo: same check treasury is an ERC1155Receiver for receiving collateral - if (_treasury == address(0)) { // Treasury address can not be zero. - revert CirclesAddressCannotBeZero(3); + revert CirclesErrorNoArgs(0x02); } - if (!nameRegistry.isValidName(_name)) { - // Invalid group name. + if (!nameRegistry.isValidName(_name) || !nameRegistry.isValidSymbol(_symbol)) { + // Invalid group name or symbol // name must be ASCII alphanumeric and some special characters - revert CirclesInvalidString(_name, 0); - } - if (!nameRegistry.isValidSymbol(_symbol)) { - // Invalid group symbol. - // symbol must be ASCII alphanumeric and some special characters - revert CirclesInvalidString(_symbol, 1); + revert CirclesErrorNoArgs(0x03); } // insert avatar into linked list; reverts if it already exists @@ -1041,16 +1053,17 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { emit Trust(_truster, _trustee, _expiry); } - function _ensureAvatarsRegistered(address[] calldata _avatars) internal returns (uint256) { + function _ensureAvatarsRegistered(address _inviter, address[] calldata _avatars) internal returns (uint256) { uint256 registrationCount = 0; for (uint256 i = 0; i < _avatars.length; i++) { if (avatars[_avatars[i]] == address(0)) { registrationCount++; - _registerHuman(_avatars[i]); + _registerHuman(_avatars[i], _inviter); } else { if (!isHuman(_avatars[i])) { // Only humans can be registered. - revert CirclesHubMustBeHuman(_avatars[i], 5); + // revert CirclesHubMustBeHuman(_avatars[i], 5); + revert CirclesErrorOneAddressArg(_avatars[i], 0x05); } } } @@ -1111,13 +1124,16 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { // as this marks whether an avatar is registered as human or not if (mintTime.lastMintTime == 0) { // Avatar must already be registered as human before we call update - revert CirclesLogicAssertion(0); + // revert CirclesLogicAssertion(0); + revert CirclesErrorNoArgs(0x80); } // if the status has changed, update the last mint time // to avoid possible overlap of the mint between Hub v1 and Hub v2 if (mintTime.mintV1Status != _mintV1Status) { mintTime.mintV1Status = _mintV1Status; - mintTime.lastMintTime = uint96(block.timestamp); + // for last mint time take the maximum to avoid resetting "INDEFINITE_FUTURE" + // which indicates stopped status of the human + mintTime.lastMintTime = uint96(_max(mintTime.lastMintTime, uint96(block.timestamp))); } } @@ -1129,7 +1145,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { function _insertAvatar(address _avatar) internal { if (avatars[_avatar] != address(0)) { // Avatar already inserted - revert CirclesHubAvatarAlreadyRegistered(_avatar, 0); + // revert CirclesHubAvatarAlreadyRegistered(_avatar, 0); + revert CirclesErrorOneAddressArg(_avatar, 0x80); } avatars[_avatar] = avatars[SENTINEL]; avatars[SENTINEL] = _avatar; @@ -1159,7 +1176,8 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { { if (_packedData.length != _numberOfTriplets * 6) { // Invalid packed data length - revert CirclesArraysLengthMismatch(_packedData.length, _numberOfTriplets, 6); + // revert CirclesArraysLengthMismatch(_packedData.length, _numberOfTriplets, 6); + revert CirclesErrorNoArgs(0xA6); } unpackedCoordinates_ = new uint16[](_numberOfTriplets * 3); @@ -1182,9 +1200,9 @@ contract Hub is Circles, TypeDefinitions, IHubErrors { * It will update the expiry time for the trusted address. */ function _upsertTrustMarker(address _truster, address _trusted, uint96 _expiry) private { - if (_truster == address(0)) revert CirclesLogicAssertion(1); - if (_trusted == address(0)) revert CirclesLogicAssertion(2); - if (_trusted == SENTINEL) revert CirclesLogicAssertion(3); + if (_truster == address(0) || _trusted == address(0) || _trusted == SENTINEL) { + revert CirclesErrorNoArgs(0x81); // CirclesLogicAssertion(1); + } TrustMarker storage sentinelMarker = trustMarkers[_truster][SENTINEL]; if (sentinelMarker.previous == address(0)) { diff --git a/src/lift/DemurrageCircles.sol b/src/lift/DemurrageCircles.sol index 81ff621..5b674b3 100644 --- a/src/lift/DemurrageCircles.sol +++ b/src/lift/DemurrageCircles.sol @@ -27,7 +27,8 @@ contract DemurrageCircles is MasterCopyNonUpgradable, ERC20DiscountedBalances, E modifier onlyHub(uint8 _code) { if (msg.sender != address(hub)) { - revert CirclesInvalidFunctionCaller(msg.sender, address(hub), _code); + // revert CirclesInvalidFunctionCaller(msg.sender, address(hub), _code); + revert CirclesErrorOneAddressArg(msg.sender, _code); } _; } @@ -46,14 +47,17 @@ contract DemurrageCircles is MasterCopyNonUpgradable, ERC20DiscountedBalances, E revert CirclesProxyAlreadyInitialized(); } if (address(_hub) == address(0)) { - revert CirclesAddressCannotBeZero(0); + // revert CirclesAddressCannotBeZero(0); + revert CirclesErrorNoArgs(0x04); } if (address(_nameRegistry) == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(1); + // revert CirclesAddressCannotBeZero(1); + revert CirclesErrorNoArgs(0x05); } if (_avatar == address(0)) { - revert CirclesAddressCannotBeZero(2); + // revert CirclesAddressCannotBeZero(2); + revert CirclesErrorNoArgs(0x06); } hub = IHubV2(_hub); avatar = _avatar; @@ -97,7 +101,7 @@ contract DemurrageCircles is MasterCopyNonUpgradable, ERC20DiscountedBalances, E function onERC1155Received(address, address _from, uint256 _id, uint256 _amount, bytes memory) public override - onlyHub(0) + onlyHub(0xE1) returns (bytes4) { if (_id != toTokenId(avatar)) revert CirclesInvalidCirclesId(_id, 0); @@ -114,7 +118,7 @@ contract DemurrageCircles is MasterCopyNonUpgradable, ERC20DiscountedBalances, E public view override - onlyHub(1) + onlyHub(0xE2) returns (bytes4) { revert CirclesERC1155CannotReceiveBatch(0); diff --git a/src/lift/ERC20DiscountedBalances.sol b/src/lift/ERC20DiscountedBalances.sol index 9efbb13..5b206e2 100644 --- a/src/lift/ERC20DiscountedBalances.sol +++ b/src/lift/ERC20DiscountedBalances.sol @@ -18,6 +18,10 @@ contract ERC20DiscountedBalances is ERC20Permit, BatchedDemurrage, IERC20 { */ mapping(address => DiscountedBalance) public discountedBalances; + // Events + + event DiscountCost(address indexed account, uint256 discountCost); + // Constructor // External functions @@ -79,9 +83,10 @@ contract ERC20DiscountedBalances is ERC20Permit, BatchedDemurrage, IERC20 { DiscountedBalance memory discountedBalance = discountedBalances[_account]; if (_day < discountedBalance.lastUpdatedDay) { // ERC20 DiscountedBalances: day is before last updated day - revert CirclesDemurrageDayBeforeLastUpdatedDay( - _account, toTokenId(avatar), _day, discountedBalance.lastUpdatedDay, 0 - ); + // revert CirclesDemurrageDayBeforeLastUpdatedDay( + // _account, toTokenId(avatar), _day, discountedBalance.lastUpdatedDay, 0 + // ); + revert CirclesErrorAddressUintArgs(_account, discountedBalance.lastUpdatedDay, 0xA2); } uint256 dayDifference; unchecked { @@ -105,7 +110,8 @@ contract ERC20DiscountedBalances is ERC20Permit, BatchedDemurrage, IERC20 { function _updateBalance(address _account, uint256 _balance, uint64 _day) internal { if (_balance > MAX_VALUE) { // Balance exceeds maximum value. - revert CirclesDemurrageAmountExceedsMaxUint190(_account, toTokenId(avatar), _balance, 0); + // revert CirclesDemurrageAmountExceedsMaxUint192(_account, toTokenId(avatar), _balance, 0); + revert CirclesErrorAddressUintArgs(_account, toTokenId(avatar), 0x83); } DiscountedBalance memory discountedBalance = discountedBalances[_account]; discountedBalance.balance = uint192(_balance); @@ -117,9 +123,10 @@ contract ERC20DiscountedBalances is ERC20Permit, BatchedDemurrage, IERC20 { DiscountedBalance memory discountedBalance = discountedBalances[_account]; if (_day < discountedBalance.lastUpdatedDay) { // ERC20 DiscountedBalances: day is before last updated day - revert CirclesDemurrageDayBeforeLastUpdatedDay( - _account, toTokenId(avatar), _day, discountedBalance.lastUpdatedDay, 1 - ); + // revert CirclesDemurrageDayBeforeLastUpdatedDay( + // _account, toTokenId(avatar), _day, discountedBalance.lastUpdatedDay, 1 + // ); + revert CirclesErrorAddressUintArgs(_account, discountedBalance.lastUpdatedDay, 0xA3); } uint256 dayDifference; unchecked { @@ -130,12 +137,14 @@ contract ERC20DiscountedBalances is ERC20Permit, BatchedDemurrage, IERC20 { uint256 discountCost = discountedBalance.balance - discountedBalanceOnDay; if (discountCost > 0) { emit Transfer(_account, address(0), discountCost); + emit DiscountCost(_account, discountCost); } } uint256 updatedBalance = discountedBalanceOnDay + _value; if (updatedBalance > MAX_VALUE) { // Balance exceeds maximum value. - revert CirclesDemurrageAmountExceedsMaxUint190(_account, toTokenId(avatar), updatedBalance, 1); + // revert CirclesDemurrageAmountExceedsMaxUint192(_account, toTokenId(avatar), updatedBalance, 1); + revert CirclesErrorAddressUintArgs(_account, toTokenId(avatar), 0x84); } discountedBalance.balance = uint192(updatedBalance); discountedBalance.lastUpdatedDay = _day; @@ -150,6 +159,7 @@ contract ERC20DiscountedBalances is ERC20Permit, BatchedDemurrage, IERC20 { } if (discountCost > 0) { emit Transfer(_from, address(0), discountCost); + emit DiscountCost(_from, discountCost); } unchecked { _updateBalance(_from, fromBalance - _amount, day); @@ -172,6 +182,7 @@ contract ERC20DiscountedBalances is ERC20Permit, BatchedDemurrage, IERC20 { } if (discountCost > 0) { emit Transfer(_owner, address(0), discountCost); + emit DiscountCost(_owner, discountCost); } unchecked { _updateBalance(_owner, ownerBalance - _amount, day); diff --git a/src/lift/ERC20Lift.sol b/src/lift/ERC20Lift.sol index 1196f15..d3ccd25 100644 --- a/src/lift/ERC20Lift.sol +++ b/src/lift/ERC20Lift.sol @@ -8,7 +8,7 @@ import "../hub/IHub.sol"; import "../names/INameRegistry.sol"; import "../proxy/ProxyFactory.sol"; -contract ERC20Lift is ProxyFactory, IERC20Lift, ICirclesErrors { +contract ERC20Lift is ProxyFactory, IERC20Lift, ICirclesErrors, ICirclesCompactErrors { // Constants bytes4 public constant ERC20_WRAPPER_SETUP_CALLPREFIX = bytes4(keccak256("setup(address,address,address)")); @@ -40,19 +40,23 @@ contract ERC20Lift is ProxyFactory, IERC20Lift, ICirclesErrors { ) { if (address(_hub) == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(0); + // revert CirclesAddressCannotBeZero(0); + revert CirclesErrorNoArgs(0x07); } if (address(_nameRegistry) == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(1); + // revert CirclesAddressCannotBeZero(1); + revert CirclesErrorNoArgs(0x08); } if (_masterCopyERC20Demurrage == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(3); + // revert CirclesAddressCannotBeZero(3); + revert CirclesErrorNoArgs(0x09); } if (_masterCopyERC20Inflation == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(4); + // revert CirclesAddressCannotBeZero(4); + revert CirclesErrorNoArgs(0x0A); } hub = _hub; @@ -63,13 +67,9 @@ contract ERC20Lift is ProxyFactory, IERC20Lift, ICirclesErrors { masterCopyERC20Wrapper[uint256(CirclesType.Inflation)] = _masterCopyERC20Inflation; } - // External functions - // Public functions function ensureERC20(address _avatar, CirclesType _circlesType) public returns (address) { - // todo: first build a simple proxy factory, afterwards redo for create2 deployment - // bytes32 salt = keccak256(abi.encodePacked(_id)); if (_circlesType != CirclesType.Demurrage && _circlesType != CirclesType.Inflation) { // Must be a valid CirclesType. revert CirclesInvalidParameter(uint256(_circlesType), 0); @@ -77,9 +77,12 @@ contract ERC20Lift is ProxyFactory, IERC20Lift, ICirclesErrors { if (msg.sender != address(hub)) { // if the Hub calls it already has checked valid avatar - if (hub.avatars(_avatar) == address(0)) { - // Avatar must be registered. - revert CirclesAvatarMustBeRegistered(_avatar, 0); + // so when called independent from the Hub, check if the avatar + // is a registered human or group + if (!(hub.isHuman(_avatar) || hub.isGroup(_avatar))) { + // Avatar must be registered (as human or group) + // revert CirclesAvatarMustBeRegistered(_avatar, 0); + revert CirclesErrorOneAddressArg(_avatar, 0x26); } } diff --git a/src/lift/InflationaryCircles.sol b/src/lift/InflationaryCircles.sol index 720a8b7..b488e71 100644 --- a/src/lift/InflationaryCircles.sol +++ b/src/lift/InflationaryCircles.sol @@ -31,7 +31,8 @@ contract InflationaryCircles is MasterCopyNonUpgradable, ERC20InflationaryBalanc modifier onlyHub(uint8 _code) { if (msg.sender != address(hub)) { - revert CirclesInvalidFunctionCaller(msg.sender, address(hub), _code); + // revert CirclesInvalidFunctionCaller(msg.sender, address(hub), _code); + revert CirclesErrorOneAddressArg(msg.sender, _code); } _; } @@ -52,15 +53,18 @@ contract InflationaryCircles is MasterCopyNonUpgradable, ERC20InflationaryBalanc } if (address(_hub) == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(0); + // revert CirclesAddressCannotBeZero(0); + revert CirclesErrorNoArgs(0x0B); } if (address(_nameRegistry) == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(1); + // revert CirclesAddressCannotBeZero(1); + revert CirclesErrorNoArgs(0x0C); } if (_avatar == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(2); + // revert CirclesAddressCannotBeZero(2); + revert CirclesErrorNoArgs(0x0D); } hub = IHubV2(_hub); avatar = _avatar; @@ -86,7 +90,7 @@ contract InflationaryCircles is MasterCopyNonUpgradable, ERC20InflationaryBalanc } function name() external view returns (string memory) { - // append suffix for "ERC20 static" to the ERC20 name + // append suffix for "-ERC20s" to the ERC20 name (s for "static") return string(abi.encodePacked(nameRegistry.name(avatar), "-ERC20s")); } @@ -103,7 +107,7 @@ contract InflationaryCircles is MasterCopyNonUpgradable, ERC20InflationaryBalanc function onERC1155Received(address, address _from, uint256 _id, uint256 _amount, bytes memory) public override - onlyHub(0) + onlyHub(0xE3) returns (bytes4) { if (_id != toTokenId(avatar)) revert CirclesInvalidCirclesId(_id, 0); @@ -119,7 +123,7 @@ contract InflationaryCircles is MasterCopyNonUpgradable, ERC20InflationaryBalanc public view override - onlyHub(1) + onlyHub(0xE4) returns (bytes4) { revert CirclesERC1155CannotReceiveBatch(0); diff --git a/src/migration/Migration.sol b/src/migration/Migration.sol index 2830d9a..94776ff 100644 --- a/src/migration/Migration.sol +++ b/src/migration/Migration.sol @@ -6,7 +6,7 @@ import "../hub/IHub.sol"; import "./IHub.sol"; import "./IToken.sol"; -contract Migration is ICirclesErrors { +contract Migration is ICirclesErrors, IMigrationErrors, ICirclesCompactErrors { // Constant uint256 private constant ACCURACY = uint256(10 ** 8); @@ -32,11 +32,13 @@ contract Migration is ICirclesErrors { constructor(IHubV1 _hubV1, IHubV2 _hubV2, uint256 _inflationDayZero) { if (address(_hubV1) == address(0)) { // Hub v1 address can not be zero. - revert CirclesAddressCannotBeZero(0); + // revert CirclesAddressCannotBeZero(0); + revert CirclesErrorNoArgs(0x0E); } if (address(_hubV2) == address(0)) { // Hub v2 address can not be zero. - revert CirclesAddressCannotBeZero(1); + // revert CirclesAddressCannotBeZero(1); + revert CirclesErrorNoArgs(0x0F); } hubV1 = _hubV1; @@ -64,7 +66,8 @@ contract Migration is ICirclesErrors { function migrate(address[] calldata _avatars, uint256[] calldata _amounts) external returns (uint256[] memory) { if (_avatars.length != _amounts.length) { // Arrays length mismatch. - revert CirclesArraysLengthMismatch(_avatars.length, _amounts.length, 0); + // revert CirclesArraysLengthMismatch(_avatars.length, _amounts.length, 0); + revert CirclesErrorNoArgs(0xA7); } uint256[] memory convertedAmounts = new uint256[](_avatars.length); @@ -73,7 +76,12 @@ contract Migration is ICirclesErrors { ITokenV1 circlesV1 = ITokenV1(hubV1.userToToken(_avatars[i])); if (address(circlesV1) == address(0)) { // Invalid avatar, not registered in hub V1. - revert CirclesAddressCannotBeZero(2); + // revert CirclesAddressCannotBeZero(2); + revert CirclesErrorNoArgs(0x10); + } + if (_amounts[i] == 0) { + // Amount must be greater than zero. + revert CirclesMigrationAmountMustBeGreaterThanZero(); } convertedAmounts[i] = convertFromV1ToDemurrage(_amounts[i]); // transfer the v1 Circles to this contract to be locked diff --git a/src/names/NameRegistry.sol b/src/names/NameRegistry.sol index fff400a..42cf604 100644 --- a/src/names/NameRegistry.sol +++ b/src/names/NameRegistry.sol @@ -6,7 +6,7 @@ import "../hub/IHub.sol"; import "./Base58Converter.sol"; import "./INameRegistry.sol"; -contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, ICirclesErrors { +contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, ICirclesErrors, ICirclesCompactErrors { // Constants /** @@ -63,16 +63,10 @@ contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, IC // Modifiers - modifier mustBeRegistered(address _avatar, uint8 _code) { - if (hub.avatars(_avatar) == address(0)) { - revert CirclesAvatarMustBeRegistered(_avatar, _code); - } - _; - } - modifier onlyHub(uint8 _code) { if (msg.sender != address(hub)) { - revert CirclesInvalidFunctionCaller(msg.sender, address(hub), _code); + // revert CirclesInvalidFunctionCaller(msg.sender, address(hub), _code); + revert CirclesErrorOneAddressArg(msg.sender, _code); } _; } @@ -82,9 +76,14 @@ contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, IC constructor(IHubV2 _hub) { if (address(_hub) == address(0)) { // Hub cannot be the zero address. - revert CirclesAddressCannotBeZero(0); + // revert CirclesAddressCannotBeZero(0); + revert CirclesErrorNoArgs(0x11); } hub = _hub; + + // register the hub itself in the name registry + customNames[address(_hub)] = "Circles"; + customSymbols[address(_hub)] = "CRC"; } // External functions @@ -92,7 +91,7 @@ contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, IC /** * @notice Register a short name for the avatar */ - function registerShortName() external mustBeRegistered(msg.sender, 0) { + function registerShortName() external { _registerShortName(); } @@ -100,19 +99,19 @@ contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, IC * Registers a short name for the avatar using a specific nonce if the short name is available * @param _nonce nonce to be used in the calculation */ - function registerShortNameWithNonce(uint256 _nonce) external mustBeRegistered(msg.sender, 1) { + function registerShortNameWithNonce(uint256 _nonce) external { _registerShortNameWithNonce(_nonce); } - function setMetadataDigest(address _avatar, bytes32 _metadataDigest) external onlyHub(0) { + function setMetadataDigest(address _avatar, bytes32 _metadataDigest) external onlyHub(0xE5) { _setMetadataDigest(_avatar, _metadataDigest); } - function updateMetadataDigest(bytes32 _metadataDigest) external mustBeRegistered(msg.sender, 2) { + function updateMetadataDigest(bytes32 _metadataDigest) external { _setMetadataDigest(msg.sender, _metadataDigest); } - function registerCustomName(address _avatar, string calldata _name) external onlyHub(1) { + function registerCustomName(address _avatar, string calldata _name) external onlyHub(0xE6) { if (bytes(_name).length == 0) { // if name is left empty, it will default to default name "Circles-" return; @@ -123,7 +122,7 @@ contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, IC customNames[_avatar] = _name; } - function registerCustomSymbol(address _avatar, string calldata _symbol) external onlyHub(2) { + function registerCustomSymbol(address _avatar, string calldata _symbol) external onlyHub(0xE7) { if (bytes(_symbol).length == 0) { // if symbol is left empty, it will default to default symbol "CRC" return; @@ -134,7 +133,7 @@ contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, IC customSymbols[_avatar] = _symbol; } - function name(address _avatar) external view mustBeRegistered(_avatar, 3) returns (string memory) { + function name(address _avatar) external view returns (string memory) { if (!hub.isHuman(_avatar)) { // groups and organizations can have set a custom name string memory customName = customNames[_avatar]; @@ -148,7 +147,7 @@ contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, IC return _getShortOrLongName(_avatar); } - function symbol(address _avatar) external view mustBeRegistered(_avatar, 4) returns (string memory) { + function symbol(address _avatar) external view returns (string memory) { if (hub.isOrganization(_avatar)) { revert CirclesNamesOrganizationHasNoSymbol(_avatar, 0); } @@ -292,6 +291,11 @@ contract NameRegistry is Base58Converter, INameRegistry, INameRegistryErrors, IC } function _storeShortName(address _avatar, uint72 _shortName, uint256 _nonce) internal { + if (_shortName == uint72(0)) { + // short name cannot be zero (but congrats if you got it!) + // this would break the reverse lookup + revert CirclesNamesShortNameZero(_avatar, _nonce); + } // assign the name to the address shortNames[_avatar] = _shortName; // assign the address to the name diff --git a/src/operators/BaseOperator.sol b/src/operators/BaseOperator.sol index 5060689..0a73038 100644 --- a/src/operators/BaseOperator.sol +++ b/src/operators/BaseOperator.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.24; import "../errors/Errors.sol"; import "../hub/IHub.sol"; -contract BaseOperator is ICirclesErrors { +contract BaseOperator is ICirclesErrors, ICirclesCompactErrors { // State variables IHubV2 public hub; @@ -14,7 +14,8 @@ contract BaseOperator is ICirclesErrors { constructor(IHubV2 _hub) { if (address(_hub) == address(0)) { // Must not be the zero address. - revert CirclesAddressCannotBeZero(0); + // revert CirclesAddressCannotBeZero(0); + revert CirclesErrorNoArgs(0x12); } hub = _hub; diff --git a/src/operators/SignedPathOperator.sol b/src/operators/SignedPathOperator.sol index f7948e8..936b1e3 100644 --- a/src/operators/SignedPathOperator.sol +++ b/src/operators/SignedPathOperator.sol @@ -29,7 +29,8 @@ contract SignedPathOperator is BaseOperator, TypeDefinitions { address source = _flowVertices[_sourceCoordinate]; // Ensure the source is the caller if (msg.sender != source) { - revert CirclesInvalidFunctionCaller(msg.sender, source, 0); + // revert CirclesInvalidFunctionCaller(msg.sender, source, 0); + revert CirclesErrorOneAddressArg(msg.sender, 0xEA); } // check that for every stream the source of the stream matches the alleged single source diff --git a/src/treasury/StandardTreasury.sol b/src/treasury/StandardTreasury.sol index 3437ba5..081bbe5 100644 --- a/src/treasury/StandardTreasury.sol +++ b/src/treasury/StandardTreasury.sol @@ -17,7 +17,8 @@ contract StandardTreasury is TypeDefinitions, IERC1155Receiver, ICirclesErrors, - IStandardTreasuryErrors + IStandardTreasuryErrors, + ICirclesCompactErrors { // Constants @@ -50,8 +51,8 @@ contract StandardTreasury is // Events event CreateVault(address indexed group, address indexed vault); - event GroupMintSingle(address indexed group, uint256 indexed id, uint256 value, bytes userData); - event GroupMintBatch(address indexed group, uint256[] ids, uint256[] values, bytes userData); + event CollateralLockedSingle(address indexed group, uint256 indexed id, uint256 value, bytes userData); + event CollateralLockedBatch(address indexed group, uint256[] ids, uint256[] values, bytes userData); event GroupRedeem(address indexed group, uint256 indexed id, uint256 value, bytes data); event GroupRedeemCollateralReturn(address indexed group, address indexed to, uint256[] ids, uint256[] values); event GroupRedeemCollateralBurn(address indexed group, uint256[] ids, uint256[] values); @@ -61,10 +62,11 @@ contract StandardTreasury is /** * @notice Ensure the caller is the hub */ - modifier onlyHub() { + modifier onlyHub(uint8 _code) { if (msg.sender != address(hub)) { // Treasury: caller is not the hub - revert CirclesInvalidFunctionCaller(msg.sender, address(hub), 0); + // revert CirclesInvalidFunctionCaller(msg.sender, address(hub), 0); + revert CirclesErrorOneAddressArg(msg.sender, _code); } _; } @@ -79,11 +81,13 @@ contract StandardTreasury is constructor(IHubV2 _hub, address _mastercopyStandardVault) { if (address(_hub) == address(0)) { // Hub address cannot be 0 - revert CirclesAddressCannotBeZero(0); + // revert CirclesAddressCannotBeZero(0); + revert CirclesErrorNoArgs(0x13); } if (_mastercopyStandardVault == address(0)) { // Mastercopy standard vault address cannot be 0 - revert CirclesAddressCannotBeZero(1); + // revert CirclesAddressCannotBeZero(1); + revert CirclesErrorNoArgs(0x14); } hub = _hub; mastercopyStandardVault = _mastercopyStandardVault; @@ -105,14 +109,14 @@ contract StandardTreasury is function onERC1155Received(address _operator, address _from, uint256 _id, uint256 _value, bytes calldata _data) public override - onlyHub + onlyHub(0xE8) returns (bytes4) { (bytes32 metadataType, address group, bytes memory userData) = _decodeMetadataForGroup(_data); if (metadataType == METADATATYPE_GROUPMINT) { - return _mintGroupCircles(_id, _value, group, userData); + return _lockCollateralGroupCircles(_id, _value, group, userData); } else if (metadataType == METADATATYPE_GROUPREDEEM) { - return _redeemGroupCircles(_operator, _from, _id, _value, _data); + return _redeemGroupCircles(_operator, _from, _id, _value, userData); } else { // Treasury: Invalid metadata type for received revert CirclesStandardTreasuryInvalidMetadataType(metadataType, 0); @@ -129,10 +133,10 @@ contract StandardTreasury is uint256[] memory _ids, uint256[] memory _values, bytes calldata _data - ) public override onlyHub returns (bytes4) { + ) public override onlyHub(0xE9) returns (bytes4) { (bytes32 metadataType, address group, bytes memory userData) = _decodeMetadataForGroup(_data); if (metadataType == METADATATYPE_GROUPMINT) { - return _mintBatchGroupCircles(_ids, _values, group, userData); + return _lockCollateralBatchGroupCircles(_ids, _values, group, userData); } else { // Treasury: Invalid metadata type for batch received revert CirclesStandardTreasuryInvalidMetadataType(metadataType, 1); @@ -144,7 +148,7 @@ contract StandardTreasury is // onReceived : either mint if data decodes or redeem // onBatchReceived : only for minting if data matches - function _mintBatchGroupCircles( + function _lockCollateralBatchGroupCircles( uint256[] memory _ids, uint256[] memory _values, address _group, @@ -155,13 +159,13 @@ contract StandardTreasury is // forward the Circles to the vault hub.safeBatchTransferFrom(address(this), vault, _ids, _values, _userData); - // emit the group mint event - emit GroupMintBatch(_group, _ids, _values, _userData); + // emit the collateral locked event + emit CollateralLockedBatch(_group, _ids, _values, _userData); return this.onERC1155BatchReceived.selector; } - function _mintGroupCircles(uint256 _id, uint256 _value, address _group, bytes memory _userData) + function _lockCollateralGroupCircles(uint256 _id, uint256 _value, address _group, bytes memory _userData) internal returns (bytes4) { @@ -170,13 +174,13 @@ contract StandardTreasury is // forward the Circles to the vault hub.safeTransferFrom(address(this), vault, _id, _value, _userData); - // emit the group mint event - emit GroupMintSingle(_group, _id, _value, _userData); + // emit the collateral locked event + emit CollateralLockedSingle(_group, _id, _value, _userData); return this.onERC1155Received.selector; } - function _redeemGroupCircles(address _operator, address _from, uint256 _id, uint256 _value, bytes calldata _data) + function _redeemGroupCircles(address _operator, address _from, uint256 _id, uint256 _value, bytes memory _userData) internal returns (bytes4) { @@ -191,7 +195,8 @@ contract StandardTreasury is IMintPolicy policy = IMintPolicy(hub.mintPolicies(group)); if (address(policy) == address(0)) { // Treasury: Invalid group without mint policy - revert CirclesLogicAssertion(0); + // revert CirclesLogicAssertion(0); + revert CirclesErrorNoArgs(0x85); } // query the mint policy for the redemption values @@ -200,7 +205,7 @@ contract StandardTreasury is uint256[] memory burnIds; uint256[] memory burnValues; (redemptionIds, redemptionValues, burnIds, burnValues) = - policy.beforeRedeemPolicy(_operator, _from, group, _value, _data); + policy.beforeRedeemPolicy(_operator, _from, group, _value, _userData); // ensure the redemption values sum up to the correct amount uint256 sum = 0; @@ -218,16 +223,16 @@ contract StandardTreasury is } // burn the group Circles - hub.burn(_id, _value, _data); + hub.burn(_id, _value, _userData); // return collateral Circles to the redeemer of group Circles - vault.returnCollateral(_from, redemptionIds, redemptionValues, _data); + vault.returnCollateral(_from, redemptionIds, redemptionValues, _userData); // burn the collateral Circles from the vault - vault.burnCollateral(burnIds, burnValues, _data); + vault.burnCollateral(burnIds, burnValues, _userData); // emit the group redeem event - emit GroupRedeem(group, _id, _value, _data); + emit GroupRedeem(group, _id, _value, _userData); emit GroupRedeemCollateralReturn(group, _from, redemptionIds, redemptionValues); emit GroupRedeemCollateralBurn(group, burnIds, burnValues); diff --git a/src/treasury/StandardVault.sol b/src/treasury/StandardVault.sol index 15b695b..049473c 100644 --- a/src/treasury/StandardVault.sol +++ b/src/treasury/StandardVault.sol @@ -7,7 +7,13 @@ import "../hub/IHub.sol"; import "../proxy/MasterCopyNonUpgradable.sol"; import "./IStandardVault.sol"; -contract StandardVault is MasterCopyNonUpgradable, ERC1155Holder, IStandardVault, ICirclesErrors { +contract StandardVault is + MasterCopyNonUpgradable, + ERC1155Holder, + IStandardVault, + ICirclesErrors, + ICirclesCompactErrors +{ // State variables /** @@ -28,7 +34,8 @@ contract StandardVault is MasterCopyNonUpgradable, ERC1155Holder, IStandardVault modifier onlyTreasury() { if (msg.sender != standardTreasury) { // Vault: caller is not the treasury - revert CirclesInvalidFunctionCaller(msg.sender, standardTreasury, 0); + // revert CirclesInvalidFunctionCaller(msg.sender, standardTreasury, 0); + revert CirclesErrorOneAddressArg(msg.sender, 0xEB); } _; } @@ -74,7 +81,8 @@ contract StandardVault is MasterCopyNonUpgradable, ERC1155Holder, IStandardVault ) external onlyTreasury { if (_receiver == address(0)) { // Vault: receiver cannot be 0 address - revert CirclesAddressCannotBeZero(0); + // revert CirclesAddressCannotBeZero(0); + revert CirclesErrorNoArgs(0x15); } // return the collateral to the receiver @@ -93,7 +101,8 @@ contract StandardVault is MasterCopyNonUpgradable, ERC1155Holder, IStandardVault { if (_ids.length != _values.length) { // Vault: ids and values length mismatch - revert CirclesArraysLengthMismatch(_ids.length, _values.length, 0); + // revert CirclesArraysLengthMismatch(_ids.length, _values.length, 0); + revert CirclesErrorNoArgs(0xA8); } // burn the collateral from the vault