From ac5c3353f6f1b486d8bce60ea1b63ffc6c328d83 Mon Sep 17 00:00:00 2001 From: I know Date: Wed, 17 May 2023 15:01:43 +0800 Subject: [PATCH] Feature/delegation tss (#837) * modify stake,slash,reward contract base on delegation lib * modify stake,slash,reward contract base on delegation lib * modify stake,slash,reward contract base on delegation lib * modify stake,slash,reward contract base on delegation lib * modify stake,slash,reward contract base on delegation lib * modify stake,slash,reward contract base on delegation lib * modify slash logic in tss module * modify slash logic in tss module * fix some bug in stakingslashing contract * remove log * add event in contracts --- go.work.sum | 33 ++ ops/config/tss-manager-config.toml | 1 + ops/scripts/deployer.sh | 21 +- packages/contracts/addresses.json | 42 +- packages/contracts/addresses.txt | 42 +- .../contracts/L1/delegation/Delegation.sol | 76 +-- .../L1/delegation/DelegationManager.sol | 37 +- .../delegation/DelegationManagerStorage.sol | 2 +- .../L1/delegation/DelegationShareBase.sol | 8 + .../contracts/L1/tss/ITssGroupManager.sol | 2 + .../contracts/L1/tss/ITssStakingSlashing.sol | 35 +- .../contracts/L1/tss/TssGroupManager.sol | 29 +- .../contracts/L1/tss/TssStakingSlashing.sol | 436 +++++++++++------- .../L1/tss/delegation/TssDelegation.sol | 68 +++ .../tss/delegation/TssDelegationManager.sol | 412 +++++++++++++++++ .../tss/delegation/TssDelegationSlasher.sol | 19 + .../L2/predeploys/TssRewardContract.sol | 173 +++++-- .../L2/predeploys/iTssRewardContract.sol | 28 ++ packages/contracts/deploy/010-TssContracts.ts | 154 ++++++- packages/contracts/filenames.txt | 12 +- packages/contracts/genesis/addresses.json | 42 +- packages/contracts/genesis/local.json | 6 +- .../contracts/genesis/state-dump.latest.json | 4 +- tss/common/config.go | 12 +- tss/common/types.go | 4 - tss/common/utils.go | 87 ++++ tss/manager/cmd.go | 3 + tss/manager/manage.go | 47 +- tss/manager/sign.go | 23 - tss/manager/sign_test.go | 38 +- tss/manager/slash.go | 104 ++++- tss/node/signer/sign_slash.go | 94 ---- 32 files changed, 1532 insertions(+), 562 deletions(-) create mode 100644 packages/contracts/contracts/L1/tss/delegation/TssDelegation.sol create mode 100644 packages/contracts/contracts/L1/tss/delegation/TssDelegationManager.sol create mode 100644 packages/contracts/contracts/L1/tss/delegation/TssDelegationSlasher.sol diff --git a/go.work.sum b/go.work.sum index 07e5f9ae2..9ee1064e3 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,19 +1,52 @@ +github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.8.0 h1:HHmhTEzHq6k/fJroPGzq8Biafn2X2IFKlKDhaL5gMHU= +github.com/consensys/gnark-crypto v0.8.0/go.mod h1:ZTnSzNlt98CpwYIJyk6q/KVcshYWr3fOXXFrrY8a0QQ= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w= +github.com/labstack/echo/v4 v4.9.0 h1:wPOF1CE6gvt/kmbMR4dGzWvHMPT+sAEUJOwOTtvITVY= +github.com/labstack/echo/v4 v4.9.0/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks= +github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o= +github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= +github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= +github.com/shurcooL/graphql v0.0.0-20220606043923-3cf50f8a0a29 h1:B1PEwpArrNp4dkQrfxh/abbBAOZBVp0ds+fBEOUOqOc= +github.com/shurcooL/graphql v0.0.0-20220606043923-3cf50f8a0a29/go.mod h1:AuYgA5Kyo4c7HfUmvRGs/6rGlMMV/6B1bVnB9JxJEEg= github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20220727055044-e65921a090b8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa h1:I0YcKz0I7OAhddo7ya8kMnvprhcWM045PmkBdMO9zN0= +google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/ops/config/tss-manager-config.toml b/ops/config/tss-manager-config.toml index 476be6015..48d427493 100644 --- a/ops/config/tss-manager-config.toml +++ b/ops/config/tss-manager-config.toml @@ -19,3 +19,4 @@ keygen_timeout = "1m" cpk_confirm_timeout = "10s" ask_timeout = "1m" sign_timeout = "2m" +private_key = "" diff --git a/ops/scripts/deployer.sh b/ops/scripts/deployer.sh index 87aa17465..73744d450 100755 --- a/ops/scripts/deployer.sh +++ b/ops/scripts/deployer.sh @@ -31,25 +31,16 @@ echo "test point1" if [ $CONTRACTS_TARGET_NETWORK == "local" ] ;then DEPLOY_CMD="npx hardhat deploy --network $CONTRACTS_TARGET_NETWORK" -# # fraud proof verifier deploy -# DEPLOY_VERIFIER="npx hardhat deployVerifier --verifier $VERIFIER_ENTRY_ADDRESS" -# -# # whiteListInit -# WHITELIST_INIT="npx hardhat whiteListInit --delegation $Proxy__FraudProofDelegation --manager $Proxy__FraudProofDelegationManager" -# -# # registerAsOperator -# REGISTER_AS_OPERATOR="npx hardhat registerAsOperator --delegation $Proxy__FraudProofDelegation" -# -# # fraud proof rollup stake -# ROLLUP_STAKE="npx hardhat rollupStake --manager $Proxy__FraudProofDelegationManager" + # # whiteListInit + # WHITELIST_INIT="npx hardhat whiteListInit --delegation $ROLLUP_CONTRACT_ADDRESS" + # # fraud proof verifier deploy + # DEPLOY_VERIFIER="npx hardhat deployVerifier --verifier $VERIFIER_ENTRY_ADDRESS" echo "Deploying contracts. Deployment command:" echo "$DEPLOY_CMD" eval "$DEPLOY_CMD" - echo "done DEPLOY_CMD" -# echo "$DEPLOY_VERIFIER" -# eval "$DEPLOY_VERIFIER" -# echo "done DEPLOY_VERIFIER" + # echo "$DEPLOY_VERIFIER" + # eval "$DEPLOY_VERIFIER" # echo "$WHITELIST_INIT" # eval "$WHITELIST_INIT" # echo "done WHITELIST_INIT" diff --git a/packages/contracts/addresses.json b/packages/contracts/addresses.json index f891b927b..1f1d77aa8 100644 --- a/packages/contracts/addresses.json +++ b/packages/contracts/addresses.json @@ -1,36 +1,36 @@ { - "Proxy__Verifier": "0x4f958F2C2303BDca22b739339cD633F8543BB07D", - "FraudProofDelegationSlasher": "0x91dC1bd9704151B0Bc4cAD3BB5c24494188aA00B", + "Proxy__Verifier": "0x8eC353337d109C0f8eef2200021D28C542CAe8E6", "ChainStorageContainer-SCC-batches": "0x0090171f848B2aa86918E5Ef2406Ab3d424fdd83", - "Proxy__AssertionMap": "0x86E10B59cFDFeFBCf3ED5b40D018949CbFCE8B59", + "Proxy__AssertionMap": "0x88e7b36Ae38D502e4Df97e7240560B77F6B4a58E", "BVM_EigenDataLayrFee": "0x5BA7b75fE6fE4412713acc62EC3e9eA87e4B8282", "StateCommitmentChain": "0x8BAccFF561FDe61D6bC8B6f299fFBa561d2189B9", - "Proxy__FraudProofDelegationSlasher": "0x8eC353337d109C0f8eef2200021D28C542CAe8E6", "TestBitToken": "0x92aBAD50368175785e4270ca9eFd169c949C4ce1", + "TssDelegationSlasher": "0xa83239cf2b900682001f9144144B5E5e5788A631", + "TssDelegation": "0x82e130FF187E787D5DdDFAa4f36CB59e6B1Da6dd", "ChainStorageContainer-CTC-batches": "0x7A8B94a9fA2bb0581D2EEA2fEd875FCA97494612", "Proxy__BVM_L1StandardBridge": "0x52753615226F8aC8a464bfecb11Ef798CFF3793f", - "Rollup": "0x2eC3980EcddA68E073c39afD44909f8fe0fE3000", - "Proxy__FraudProofDelegation": "0x88e7b36Ae38D502e4Df97e7240560B77F6B4a58E", - "TssStakingSlashing": "0x36fCf02Fc651c0b7ef2ECA446Dd2405364F85337", + "Proxy__TssDelegationManager": "0xE6A251EefaEE70E8645FBAdf21E9B1246e07C374", + "Rollup": "0x91dC1bd9704151B0Bc4cAD3BB5c24494188aA00B", + "TssStakingSlashing": "0x7d0f87007795438DBCF67e4a91c03Bb3eDe152dE", "BVM_L1CrossDomainMessenger": "0xD076364Fa5de1a4512c58b39ad63DD720B7B9E11", - "Proxy__TSS_GroupManager": "0xa83239cf2b900682001f9144144B5E5e5788A631", + "Proxy__TssDelegation": "0xe6cd9e7b620964bECd42c7Ad41e56724f515E284", + "Proxy__TSS_GroupManager": "0xF48398a3D94D57AE1406B343D2a7C541336Ea2c2", + "Proxy__TssDelegationSlasher": "0xD007896d9E3e4514a1f1216A91d33a72e15bf5C0", "Proxy__BVM_EigenDataLayrFee": "0xeeC65aC2497dFE595b382132E0a35E73e93f2166", "Lib_AddressManager": "0x19C22f181280dF6Ad1d97285cdD430173Df91C12", - "VerifierEntry": "0x9109811E8eEe02520219612bB5D47C60c382F4aa", - "AddressDictator": "0xE6A251EefaEE70E8645FBAdf21E9B1246e07C374", - "BVM_EigenDataLayrChain": "0xc2E4F2038D456AfEFfF2351234BCaFCB6837baC1", + "VerifierEntry": "0x1eeAdb6C93161a34b2eBE9994fD73d6B7Bc70817", + "AddressDictator": "0xC346c14AA2c1001eee47CCEc1404D193ab1667Ab", + "BVM_EigenDataLayrChain": "0x4f958F2C2303BDca22b739339cD633F8543BB07D", "CanonicalTransactionChain": "0x9faB987C9C469EB23Da31B7848B28aCf30905eA8", - "TssGroupManager": "0x82e130FF187E787D5DdDFAa4f36CB59e6B1Da6dd", - "FraudProofDelegation": "0xb416faEaEf670632Db2Ad66558e74aaD6518FB84", - "L1StandardBridge_for_verification_only": "0xdf3BD218A936A92be5e43592143ecc7a33cef514", - "Proxy__FraudProofDelegationManager": "0x90c9E4f7F11C93BCec2e1F272b2063640d3bb264", - "FraudProofDelegationManager": "0x1eeAdb6C93161a34b2eBE9994fD73d6B7Bc70817", - "ChugSplashDictator": "0x18DF7d7Cc40928f07d3EF0e5404b41F97e8560Ad", - "Proxy__BVM_EigenDataLayrChain": "0x5a0069E211A28cBD1a7dbD585877596FeD07805b", + "TssGroupManager": "0x1FB27316e91e477943A87Eb215E40Fab6b382Fda", + "L1StandardBridge_for_verification_only": "0x86E10B59cFDFeFBCf3ED5b40D018949CbFCE8B59", + "TssDelegationManager": "0x36fCf02Fc651c0b7ef2ECA446Dd2405364F85337", + "ChugSplashDictator": "0x1Edd37fc504513bAa00D782E52478d0a3f675553", + "Proxy__BVM_EigenDataLayrChain": "0x8013ac56e4c4A562b72a6D8B39D60cDa7aE173A9", "Proxy__BVM_L1CrossDomainMessenger": "0xd9e2F450525079e1e29fB23Bc7Caca6F61f8fD4a", - "Proxy__TSS_StakingSlashing": "0xe6cd9e7b620964bECd42c7Ad41e56724f515E284", + "Proxy__TSS_StakingSlashing": "0x9c28c8D298ae7Ebf8daA6FA54e1F2909313dB158", "BondManager": "0xEd5166f12FCb48a0804B62FDccB37f59F1F1bc3B", - "AssertionMap": "0x1Edd37fc504513bAa00D782E52478d0a3f675553", - "Proxy__Rollup": "0x8013ac56e4c4A562b72a6D8B39D60cDa7aE173A9", + "AssertionMap": "0xb416faEaEf670632Db2Ad66558e74aaD6518FB84", + "Proxy__Rollup": "0x90c9E4f7F11C93BCec2e1F272b2063640d3bb264", "AddressManager": "0x19C22f181280dF6Ad1d97285cdD430173Df91C12" } diff --git a/packages/contracts/addresses.txt b/packages/contracts/addresses.txt index 6ae9ef821..bd5d891fb 100644 --- a/packages/contracts/addresses.txt +++ b/packages/contracts/addresses.txt @@ -1,33 +1,33 @@ -0x4f958F2C2303BDca22b739339cD633F8543BB07D -0x91dC1bd9704151B0Bc4cAD3BB5c24494188aA00B +0x8eC353337d109C0f8eef2200021D28C542CAe8E6 0x0090171f848B2aa86918E5Ef2406Ab3d424fdd83 -0x86E10B59cFDFeFBCf3ED5b40D018949CbFCE8B59 +0x88e7b36Ae38D502e4Df97e7240560B77F6B4a58E 0x5BA7b75fE6fE4412713acc62EC3e9eA87e4B8282 0x8BAccFF561FDe61D6bC8B6f299fFBa561d2189B9 -0x8eC353337d109C0f8eef2200021D28C542CAe8E6 0x92aBAD50368175785e4270ca9eFd169c949C4ce1 +0xa83239cf2b900682001f9144144B5E5e5788A631 +0x82e130FF187E787D5DdDFAa4f36CB59e6B1Da6dd 0x7A8B94a9fA2bb0581D2EEA2fEd875FCA97494612 0x52753615226F8aC8a464bfecb11Ef798CFF3793f -0x2eC3980EcddA68E073c39afD44909f8fe0fE3000 -0x88e7b36Ae38D502e4Df97e7240560B77F6B4a58E -0x36fCf02Fc651c0b7ef2ECA446Dd2405364F85337 +0xE6A251EefaEE70E8645FBAdf21E9B1246e07C374 +0x91dC1bd9704151B0Bc4cAD3BB5c24494188aA00B +0x7d0f87007795438DBCF67e4a91c03Bb3eDe152dE 0xD076364Fa5de1a4512c58b39ad63DD720B7B9E11 -0xa83239cf2b900682001f9144144B5E5e5788A631 +0xe6cd9e7b620964bECd42c7Ad41e56724f515E284 +0xF48398a3D94D57AE1406B343D2a7C541336Ea2c2 +0xD007896d9E3e4514a1f1216A91d33a72e15bf5C0 0xeeC65aC2497dFE595b382132E0a35E73e93f2166 0x19C22f181280dF6Ad1d97285cdD430173Df91C12 -0x9109811E8eEe02520219612bB5D47C60c382F4aa -0xE6A251EefaEE70E8645FBAdf21E9B1246e07C374 -0xc2E4F2038D456AfEFfF2351234BCaFCB6837baC1 -0x9faB987C9C469EB23Da31B7848B28aCf30905eA8 -0x82e130FF187E787D5DdDFAa4f36CB59e6B1Da6dd -0xb416faEaEf670632Db2Ad66558e74aaD6518FB84 -0xdf3BD218A936A92be5e43592143ecc7a33cef514 -0x90c9E4f7F11C93BCec2e1F272b2063640d3bb264 0x1eeAdb6C93161a34b2eBE9994fD73d6B7Bc70817 -0x18DF7d7Cc40928f07d3EF0e5404b41F97e8560Ad -0x5a0069E211A28cBD1a7dbD585877596FeD07805b -0xd9e2F450525079e1e29fB23Bc7Caca6F61f8fD4a -0xe6cd9e7b620964bECd42c7Ad41e56724f515E284 -0xEd5166f12FCb48a0804B62FDccB37f59F1F1bc3B +0xC346c14AA2c1001eee47CCEc1404D193ab1667Ab +0x4f958F2C2303BDca22b739339cD633F8543BB07D +0x9faB987C9C469EB23Da31B7848B28aCf30905eA8 +0x1FB27316e91e477943A87Eb215E40Fab6b382Fda +0x86E10B59cFDFeFBCf3ED5b40D018949CbFCE8B59 +0x36fCf02Fc651c0b7ef2ECA446Dd2405364F85337 0x1Edd37fc504513bAa00D782E52478d0a3f675553 0x8013ac56e4c4A562b72a6D8B39D60cDa7aE173A9 +0xd9e2F450525079e1e29fB23Bc7Caca6F61f8fD4a +0x9c28c8D298ae7Ebf8daA6FA54e1F2909313dB158 +0xEd5166f12FCb48a0804B62FDccB37f59F1F1bc3B +0xb416faEaEf670632Db2Ad66558e74aaD6518FB84 +0x90c9E4f7F11C93BCec2e1F272b2063640d3bb264 diff --git a/packages/contracts/contracts/L1/delegation/Delegation.sol b/packages/contracts/contracts/L1/delegation/Delegation.sol index 7e81b87b8..ac0cf1fbc 100644 --- a/packages/contracts/contracts/L1/delegation/Delegation.sol +++ b/packages/contracts/contracts/L1/delegation/Delegation.sol @@ -11,7 +11,6 @@ import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; import "./DelegationStorage.sol"; import "./DelegationSlasher.sol"; import "./WhiteListBase.sol"; - /** * @title The primary delegation contract. * @notice This is the contract for delegation. The main functionalities of this contract are @@ -41,6 +40,14 @@ abstract contract Delegation is Initializable, OwnableUpgradeable, PausableUpgra /// @dev Emitted when a low-level call to `delegationTerms.onDelegationWithdrawn` fails, returning `returnData` event OnDelegationWithdrawnCallFailure(IDelegationCallback indexed delegationTerms, bytes32 returnData); + event RegisterOperator(address delegationCallback, address register); + + event DelegateTo(address delegatior, address operator); + + event DecreaseDelegatedShares(address delegatedShare, address operator, uint256 share); + + event IncreaseDelegatedShares(address delegatedShare, address operator, uint256 share); + function initialize(address initialOwner) external initializer @@ -74,6 +81,7 @@ abstract contract Delegation is Initializable, OwnableUpgradeable, PausableUpgra // store the address of the delegation contract that the operator is providing. delegationCallback[msg.sender] = dt; _delegate(msg.sender, msg.sender); + emit RegisterOperator(address(dt),msg.sender); } /** @@ -139,6 +147,7 @@ abstract contract Delegation is Initializable, OwnableUpgradeable, PausableUpgra // call into hook in delegationCallback contract IDelegationCallback dt = delegationCallback[operator]; _delegationReceivedHook(dt, staker, operator, investorDelegations, investorShares); + emit IncreaseDelegatedShares(address(delegationShare), operator, shares); } } @@ -166,6 +175,7 @@ abstract contract Delegation is Initializable, OwnableUpgradeable, PausableUpgra // call into hook in delegationCallback contract IDelegationCallback dt = delegationCallback[operator]; _delegationWithdrawnHook(dt, staker, operator, investorDelegationShares, investorShares); + emit DecreaseDelegatedShares(address(delegationShare), operator, shares); } } @@ -185,6 +195,7 @@ abstract contract Delegation is Initializable, OwnableUpgradeable, PausableUpgra uint256 stratsLength = strategies.length; for (uint256 i = 0; i < stratsLength;) { operatorShares[operator][strategies[i]] -= shares[i]; + emit DecreaseDelegatedShares(address(strategies[i]), operator, shares[i]); unchecked { ++i; } @@ -218,29 +229,10 @@ abstract contract Delegation is Initializable, OwnableUpgradeable, PausableUpgra * In particular, in-line assembly is also used to prevent the copying of uncapped return data which is also a potential DoS vector. */ // format calldata - bytes memory lowLevelCalldata = abi.encodeWithSelector(IDelegationCallback.onDelegationReceived.selector, staker, operator, delegationShares, shares); - // Prepare memory for low-level call return data. We accept a max return data length of 32 bytes - bool success; - bytes32[1] memory returnData; - // actually make the call - assembly { - success := call( - // gas provided to this context - LOW_LEVEL_GAS_BUDGET, - // address to call - dt, - // value in wei for call - 0, - // memory location to copy for calldata - lowLevelCalldata, - // length of memory to copy for calldata - mload(lowLevelCalldata), - // memory location to copy return data - returnData, - // byte size of return data to copy to memory - 32 - ) - } + (bool success, bytes memory returnData) = address(dt).call{gas: LOW_LEVEL_GAS_BUDGET}( + abi.encodeWithSelector(IDelegationCallback.onDelegationReceived.selector, staker, operator, delegationShares, shares) + ); + // if the call fails, we emit a special event rather than reverting if (!success) { emit OnDelegationReceivedCallFailure(dt, returnData[0]); @@ -266,30 +258,11 @@ abstract contract Delegation is Initializable, OwnableUpgradeable, PausableUpgra * We use low-level call functionality here to ensure that an operator cannot maliciously make this function fail in order to prevent undelegation. * In particular, in-line assembly is also used to prevent the copying of uncapped return data which is also a potential DoS vector. */ - // format calldata - bytes memory lowLevelCalldata = abi.encodeWithSelector(IDelegationCallback.onDelegationWithdrawn.selector, staker, operator, delegationShares, shares); - // Prepare memory for low-level call return data. We accept a max return data length of 32 bytes - bool success; - bytes32[1] memory returnData; - // actually make the call - assembly { - success := call( - // gas provided to this context - LOW_LEVEL_GAS_BUDGET, - // address to call - dt, - // value in wei for call - 0, - // memory location to copy for calldata - lowLevelCalldata, - // length of memory to copy for calldata - mload(lowLevelCalldata), - // memory location to copy return data - returnData, - // byte size of return data to copy to memory - 32 - ) - } + + (bool success, bytes memory returnData) = address(dt).call{gas: LOW_LEVEL_GAS_BUDGET}( + abi.encodeWithSelector(IDelegationCallback.onDelegationWithdrawn.selector, staker, operator, delegationShares, shares) + ); + // if the call fails, we emit a special event rather than reverting if (!success) { emit OnDelegationWithdrawnCallFailure(dt, returnData[0]); @@ -304,22 +277,21 @@ abstract contract Delegation is Initializable, OwnableUpgradeable, PausableUpgra * delegated, and records the new delegation. */ function _delegate(address staker, address operator) internal { + IDelegationCallback dt = delegationCallback[operator]; require( address(dt) != address(0), "Delegation._delegate: operator has not yet registered as a delegate" ); - require(isNotDelegated(staker), "Delegation._delegate: staker has existing delegation"); + // checks that operator has not been frozen IDelegationSlasher slasher = delegationManager.delegationSlasher(); require(!slasher.isFrozen(operator), "Delegation._delegate: cannot delegate to a frozen operator"); - // record delegation relation between the staker and operator delegatedTo[staker] = operator; // record that the staker is delegated delegationStatus[staker] = DelegationStatus.DELEGATED; - // retrieve list of strategies and their shares from investment manager (IDelegationShare[] memory delegationShares, uint256[] memory shares) = delegationManager.getDeposits(staker); @@ -332,9 +304,9 @@ abstract contract Delegation is Initializable, OwnableUpgradeable, PausableUpgra ++i; } } - // call into hook in delegationCallback contract _delegationReceivedHook(dt, staker, operator, delegationShares, shares); + emit DelegateTo(staker, operator); } // VIEW FUNCTIONS diff --git a/packages/contracts/contracts/L1/delegation/DelegationManager.sol b/packages/contracts/contracts/L1/delegation/DelegationManager.sol index 69283a7a0..233f02c41 100644 --- a/packages/contracts/contracts/L1/delegation/DelegationManager.sol +++ b/packages/contracts/contracts/L1/delegation/DelegationManager.sol @@ -11,7 +11,6 @@ import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; import "./interfaces/IDelegation.sol"; import "./DelegationManagerStorage.sol"; import "./WhiteListBase.sol"; - /** * @title The primary entry- and exit-point for funds into and out. * @author Layr Labs, Inc. @@ -57,13 +56,13 @@ abstract contract DelegationManager is modifier onlyNotFrozen(address staker) { require( !delegationSlasher.isFrozen(staker), - "InvestmentManager.onlyNotFrozen: staker has been frozen and may be subject to slashing" + "DelegationManager.onlyNotFrozen: staker has been frozen and may be subject to slashing" ); _; } modifier onlyFrozen(address staker) { - require(delegationSlasher.isFrozen(staker), "InvestmentManager.onlyFrozen: staker has not been frozen"); + require(delegationSlasher.isFrozen(staker), "DelegationManager.onlyFrozen: staker has not been frozen"); _; } @@ -142,6 +141,7 @@ abstract contract DelegationManager is bool undelegateIfPossible ) external + virtual whenNotPaused onlyNotFrozen(msg.sender) nonReentrant @@ -149,7 +149,7 @@ abstract contract DelegationManager is { require( withdrawerAndNonce.nonce == numWithdrawalsQueued[msg.sender], - "InvestmentManager.queueWithdrawal: provided nonce incorrect" + "DelegationManager.queueWithdrawal: provided nonce incorrect" ); // increment the numWithdrawalsQueued of the sender unchecked { @@ -228,18 +228,18 @@ abstract contract DelegationManager is * - The withdrawer completes the queued withdrawal after the stake is inactive or a withdrawal fraud proof period has passed, * whichever is longer. They specify whether they would like the withdrawal in shares or in tokens. */ - function startQueuedWithdrawalWaitingPeriod(bytes32 withdrawalRoot, uint32 stakeInactiveAfter) external { + function startQueuedWithdrawalWaitingPeriod(bytes32 withdrawalRoot, uint32 stakeInactiveAfter) external virtual { require( queuedWithdrawals[withdrawalRoot].unlockTimestamp == QUEUED_WITHDRAWAL_INITIALIZED_VALUE, - "InvestmentManager.startQueuedWithdrawalWaitingPeriod: Withdrawal stake inactive claim has already been made" + "DelegationManager.startQueuedWithdrawalWaitingPeriod: Withdrawal stake inactive claim has already been made" ); require( queuedWithdrawals[withdrawalRoot].withdrawer == msg.sender, - "InvestmentManager.startQueuedWithdrawalWaitingPeriod: Sender is not the withdrawer" + "DelegationManager.startQueuedWithdrawalWaitingPeriod: Sender is not the withdrawer" ); require( block.timestamp > queuedWithdrawals[withdrawalRoot].initTimestamp, - "InvestmentManager.startQueuedWithdrawalWaitingPeriod: Stake may still be subject to slashing based on new tasks. Wait to set stakeInactiveAfter." + "DelegationManager.startQueuedWithdrawalWaitingPeriod: Stake may still be subject to slashing based on new tasks. Wait to set stakeInactiveAfter." ); //they can only unlock after a withdrawal waiting period or after they are claiming their stake is inactive queuedWithdrawals[withdrawalRoot].unlockTimestamp = max((uint32(block.timestamp) + WITHDRAWAL_WAITING_PERIOD), stakeInactiveAfter); @@ -267,19 +267,19 @@ abstract contract DelegationManager is // verify that the queued withdrawal actually exists require( withdrawalStorageCopy.unlockTimestamp != 0, - "InvestmentManager.completeQueuedWithdrawal: withdrawal does not exist" + "DelegationManager.completeQueuedWithdrawal: withdrawal does not exist" ); require( uint32(block.timestamp) >= withdrawalStorageCopy.unlockTimestamp || (queuedWithdrawal.delegatedAddress == address(0)), - "InvestmentManager.completeQueuedWithdrawal: withdrawal waiting period has not yet passed and depositor was delegated when withdrawal initiated" + "DelegationManager.completeQueuedWithdrawal: withdrawal waiting period has not yet passed and depositor was delegated when withdrawal initiated" ); // TODO: add testing coverage for this require( msg.sender == queuedWithdrawal.withdrawerAndNonce.withdrawer, - "InvestmentManager.completeQueuedWithdrawal: only specified withdrawer can complete a queued withdrawal" + "DelegationManager.completeQueuedWithdrawal: only specified withdrawer can complete a queued withdrawal" ); // reset the storage slot in mapping of queued withdrawals @@ -332,6 +332,7 @@ abstract contract DelegationManager is uint256[] calldata shareAmounts ) external + virtual whenNotPaused onlyOwner onlyFrozen(slashedAddress) @@ -377,13 +378,13 @@ abstract contract DelegationManager is // verify that the queued withdrawal actually exists require( queuedWithdrawals[withdrawalRoot].unlockTimestamp != 0, - "InvestmentManager.slashQueuedWithdrawal: withdrawal does not exist" + "DelegationManager.slashQueuedWithdrawal: withdrawal does not exist" ); // verify that *either* the queued withdrawal has been successfully challenged, *or* the `depositor` has been frozen require( queuedWithdrawals[withdrawalRoot].withdrawer == address(0) || delegationSlasher.isFrozen(queuedWithdrawal.depositor), - "InvestmentManager.slashQueuedWithdrawal: withdrawal has not been successfully challenged or depositor is not frozen" + "DelegationManager.slashQueuedWithdrawal: withdrawal has not been successfully challenged or depositor is not frozen" ); // reset the storage slot in mapping of queued withdrawals @@ -409,13 +410,13 @@ abstract contract DelegationManager is */ function _addShares(address depositor, IDelegationShare delegationShare, uint256 shares) internal { // sanity check on `shares` input - require(shares != 0, "InvestmentManager._addShares: shares should not be zero!"); + require(shares != 0, "DelegationManager._addShares: shares should not be zero!"); // if they dont have existing shares of this delegation contract, add it to their strats if (investorDelegationShares[depositor][delegationShare] == 0) { require( investorDelegations[depositor].length <= MAX_INVESTOR_DELEGATION_LENGTH, - "InvestmentManager._addShares: deposit would exceed MAX_INVESTOR_DELEGATION_LENGTH" + "DelegationManager._addShares: deposit would exceed MAX_INVESTOR_DELEGATION_LENGTH" ); investorDelegations[depositor].push(delegationShare); } @@ -459,13 +460,13 @@ abstract contract DelegationManager is returns (bool) { // sanity check on `shareAmount` input - require(shareAmount != 0, "InvestmentManager._removeShares: shareAmount should not be zero!"); + require(shareAmount != 0, "DelegationManager._removeShares: shareAmount should not be zero!"); //check that the user has sufficient shares uint256 userShares = investorDelegationShares[depositor][delegationShare]; - require(shareAmount <= userShares, "InvestmentManager._removeShares: shareAmount too high"); + require(shareAmount <= userShares, "DelegationManager._removeShares: shareAmount too high"); //unchecked arithmetic since we just checked this above unchecked { userShares = userShares - shareAmount; @@ -544,7 +545,7 @@ abstract contract DelegationManager is // verify that the queued withdrawal actually exists require( queuedWithdrawals[withdrawalRoot].unlockTimestamp != 0, - "InvestmentManager.canCompleteQueuedWithdrawal: withdrawal does not exist" + "DelegationManager.canCompleteQueuedWithdrawal: withdrawal does not exist" ); if (delegationSlasher.isFrozen(queuedWithdrawal.delegatedAddress)) { diff --git a/packages/contracts/contracts/L1/delegation/DelegationManagerStorage.sol b/packages/contracts/contracts/L1/delegation/DelegationManagerStorage.sol index 52fb98f87..789b3c25b 100644 --- a/packages/contracts/contracts/L1/delegation/DelegationManagerStorage.sol +++ b/packages/contracts/contracts/L1/delegation/DelegationManagerStorage.sol @@ -28,7 +28,7 @@ abstract contract DelegationManagerStorage is IDelegationManager { * within `REASONABLE_STAKES_UPDATE_PERIOD` of the present moment. In other words, this is the lag between undelegation/deregistration * and the staker's/operator's funds no longer being slashable due to misbehavior *on a new task*. */ - uint256 public constant REASONABLE_STAKES_UPDATE_PERIOD = 7 days; + uint256 public constant REASONABLE_STAKES_UPDATE_PERIOD = 30 seconds; // fixed waiting period for withdrawals // TODO: set this to a proper interval for production diff --git a/packages/contracts/contracts/L1/delegation/DelegationShareBase.sol b/packages/contracts/contracts/L1/delegation/DelegationShareBase.sol index 63e145fb8..db3f0ec9d 100644 --- a/packages/contracts/contracts/L1/delegation/DelegationShareBase.sol +++ b/packages/contracts/contracts/L1/delegation/DelegationShareBase.sol @@ -27,6 +27,10 @@ abstract contract DelegationShareBase is Initializable, PausableUpgradeable, IDe /// @notice The total number of extant shares in the DelegationShare uint256 public totalShares; + event Deposit(address depositor, address token, uint256 amount); + + event Withdraw(address depositor, address token, uint256 amount); + /// @notice Simply checks that the `msg.sender` is the `DelegationManager`, which is an address stored immutably at construction. modifier onlyDelegationManager() { require(msg.sender == address(delegationManager), "DelegationShareBase.onlyDelegationManager"); @@ -63,6 +67,7 @@ abstract contract DelegationShareBase is Initializable, PausableUpgradeable, IDe } totalShares += newShares; + emit Deposit(depositor, address(token), amount); return newShares; } @@ -102,6 +107,7 @@ abstract contract DelegationShareBase is Initializable, PausableUpgradeable, IDe amountToSend = (_tokenBalance() * amountShares) / priorTotalShares; } underlyingToken.safeTransfer(depositor, amountToSend); + emit Withdraw(depositor, address(token), amountToSend); } /** @@ -191,4 +197,6 @@ abstract contract DelegationShareBase is Initializable, PausableUpgradeable, IDe function _tokenBalance() internal view virtual returns (uint256) { return underlyingToken.balanceOf(address(this)); } + + } diff --git a/packages/contracts/contracts/L1/tss/ITssGroupManager.sol b/packages/contracts/contracts/L1/tss/ITssGroupManager.sol index 8fd5615e1..3d6809163 100644 --- a/packages/contracts/contracts/L1/tss/ITssGroupManager.sol +++ b/packages/contracts/contracts/L1/tss/ITssGroupManager.sol @@ -28,4 +28,6 @@ interface ITssGroupManager { function inActiveIsEmpty() external returns (bool); function verifySign(bytes32 _message, bytes memory _sig) external returns (bool); function publicKeyToAddress (bytes memory publicKey) external returns (address); + function isTssGroupUnJailMembers(address _addr) external returns (bool); + function memberExistActive(address _addr) external returns (bool); } diff --git a/packages/contracts/contracts/L1/tss/ITssStakingSlashing.sol b/packages/contracts/contracts/L1/tss/ITssStakingSlashing.sol index 106043d86..2a27a482a 100644 --- a/packages/contracts/contracts/L1/tss/ITssStakingSlashing.sol +++ b/packages/contracts/contracts/L1/tss/ITssStakingSlashing.sol @@ -2,27 +2,38 @@ pragma solidity >0.5.0 <0.9.0; interface IStakingSlashing { - struct DepositInfo { - address pledgor; - bytes pubKey; - uint256 amount; - } // tx - function setAddress(address , address ) external; - function setSlashingParams(uint256[2] calldata , uint256[2] calldata) external; - function staking(uint256 , bytes calldata) external; - function withdrawToken() external; + function setTokenAddress(address) external; + function setTssGroupAddress(address) external; + function setRegulatoryAccount(address) external; + function setClaimer(address, address) external; + function setSlashingParams(uint256[2] calldata) external; + function setPublicKey(bytes calldata) external; function quitRequest() external; function clearQuitRequestList() external; function slashing(bytes calldata, bytes calldata) external; function unJail() external; // query - function getSlashingParams() external view returns (uint256[2] memory, uint256[2] memory); + function getSlashingParams() external view returns (uint256[2] memory); function getQuitRequestList() external view returns (address[] memory); - function getDeposits(address) external returns (DepositInfo memory); - function batchGetDeposits(address[] calldata) external view returns (DepositInfo[] memory); function getSlashRecord(uint256, address) external view returns (bool); function isJailed(address) external returns (bool); + function isCanOperator(address) external returns (bool); + + //fund + function deposit(uint256 amount) external returns (uint256); + function withdraw() external; + function completeWithdraw() external; + function startWithdraw() external; + function canCompleteQueuedWithdrawal() external returns (bool); + + //delegation + function registerAsOperator(bytes calldata) external; + function delegateTo(address) external; + + + + } diff --git a/packages/contracts/contracts/L1/tss/TssGroupManager.sol b/packages/contracts/contracts/L1/tss/TssGroupManager.sol index 1a252bc42..8b4e544dc 100644 --- a/packages/contracts/contracts/L1/tss/TssGroupManager.sol +++ b/packages/contracts/contracts/L1/tss/TssGroupManager.sol @@ -7,6 +7,7 @@ import "@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; import "./ITssGroupManager.sol"; +import "./ITssStakingSlashing.sol"; contract TssGroupManager is OwnableUpgradeable, @@ -62,7 +63,11 @@ contract TssGroupManager is { require((_batchPublicKey.length > 0), "batch public key is empty"); require(_threshold < _batchPublicKey.length, "threshold must less than tss member"); - // require((inActiveTssMembers.length == 0), "inactive tss member array is not empty"); + for (uint256 i = 0; i < _batchPublicKey.length; i++) { + address operator = publicKeyToAddress(_batchPublicKey[i]); + require(IStakingSlashing(stakingSlash).isCanOperator(operator),"batch public keys has a node ,can not be operator"); + } + if(inActiveTssMembers.length > 0) { for (uint256 i = 0; i < inActiveTssMembers.length; i++) { // re-election clear data @@ -160,7 +165,7 @@ contract TssGroupManager is * @inheritdoc ITssGroupManager */ // slither-disable-next-line external-function - function removeMember(bytes memory _publicKey) public override onlyStakingSlash { + function removeMember(bytes memory _publicKey) public override onlyOwner { for (uint256 i = 0; i < activeTssMembers.length; i++) { if (isEqual(activeTssMembers[i], _publicKey)) { removeActiveTssMembers(i); @@ -191,6 +196,26 @@ contract TssGroupManager is return _addresses; } + function isTssGroupUnJailMembers(address _addr) public view override returns (bool) { + for (uint256 i = 0; i < activeTssMembers.length; i++) { + if (tssActiveMemberInfo[activeTssMembers[i]].status == MemberStatus.unJail) { + if ( _addr == tssActiveMemberInfo[activeTssMembers[i]].nodeAddress) { + return true; + } + } + } + return false; + } + + function memberExistActive(address _addr) public view override returns (bool) { + for (uint256 i = 0; i < activeTssMembers.length; i++) { + if ( _addr == tssActiveMemberInfo[activeTssMembers[i]].nodeAddress) { + return true; + } + } + return false; + } + /** * @inheritdoc ITssGroupManager */ diff --git a/packages/contracts/contracts/L1/tss/TssStakingSlashing.sol b/packages/contracts/contracts/L1/tss/TssStakingSlashing.sol index 8a2e6a6c7..8d2adc49c 100644 --- a/packages/contracts/contracts/L1/tss/TssStakingSlashing.sol +++ b/packages/contracts/contracts/L1/tss/TssStakingSlashing.sol @@ -4,6 +4,19 @@ pragma solidity ^0.8.9; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; +import "@openzeppelin/contracts/utils/math/SafeCast.sol"; + +import {DelegationShareBase} from "../delegation/DelegationShareBase.sol"; +import {DelegationCallbackBase} from "../delegation/DelegationCallbackBase.sol"; +import {IDelegationManager} from "../delegation/interfaces/IDelegationManager.sol"; +import {IDelegationShare} from "../delegation/interfaces/IDelegation.sol"; +import {IDelegation} from "../delegation/interfaces/IDelegation.sol"; +import {CrossDomainEnabled} from "../../libraries/bridge/CrossDomainEnabled.sol"; +import {ITssRewardContract} from "../../L2/predeploys/iTssRewardContract.sol"; +import {TssDelegationManager} from "./delegation/TssDelegationManager.sol"; +import {TssDelegation} from "./delegation/TssDelegation.sol"; +import {WhiteList} from "../delegation/WhiteListBase.sol"; + import "./ITssGroupManager.sol"; import "./ITssStakingSlashing.sol"; @@ -11,7 +24,10 @@ contract TssStakingSlashing is Initializable, OwnableUpgradeable, ReentrancyGuardUpgradeable, - IStakingSlashing + IStakingSlashing, + DelegationShareBase, + DelegationCallbackBase, + CrossDomainEnabled { enum SlashType { nothing, @@ -25,37 +41,34 @@ contract TssStakingSlashing is address[] tssNodes; SlashType slashType; } - // staking parameter settings - // bit token contract address - address public BitToken; + // tss group contract address address public tssGroupContract; - // storage staker infos (key:staker address) - mapping(address => DepositInfo) public deposits; + //tss delegation manager address + address public tssDelegationManagerContract; + //tss delegation address + address public tssDelegationContract; + // storage operator infos (key:staker address) + mapping(address => bytes) public operators; // slashing parameter settings // record the quit request address[] public quitRequestList; // slashing amount of type uptime and animus (0:uptime, 1:animus) uint256[2] public slashAmount; - // additional rewards for sender (0:uptime, 1:animus) - uint256[2] public exIncome; // record the slash operate (map[batchIndex] -> (map[staker] -> slashed)) mapping(uint256 => mapping(address => bool)) slashRecord; + //EOA address + address public regulatoryAccount; + //msg sender => withdraw event + mapping(address => bytes32) public withdrawalRoots; + //msg sender => withdrawal + mapping(address => IDelegationManager.QueuedWithdrawal) public withdrawals; + //operator => stakers + mapping(address => address[]) public stakers; + //staker => operator + mapping(address => address) public delegators; - /** - * @notice staking for himself - * @param 0 staker address - * @param 1 staker public key and deposit amount - */ - event AddDeposit(address, DepositInfo); - - /** - * @notice withdraw for himself - * @param 0 staker address - * @param 1 total amount withdraw - */ - event Withdraw(address, uint256); /** * @notice slash tssnode @@ -64,131 +77,116 @@ contract TssStakingSlashing is */ event Slashing(address, SlashType); + event WithdrawQueue(address,uint256); + + + + + constructor() CrossDomainEnabled(address(0)) { + _disableInitializers(); + } + /** * @notice initializes the contract setting and the deployer as the initial owner * @param _bitToken bit token contract address * @param _tssGroupContract address tss group manager contract address */ - function initialize(address _bitToken, address _tssGroupContract) public initializer { + function initialize(address _bitToken, + address _tssGroupContract, + address _delegationManager, + address _delegation, + address _l1messenger, + address _regulatoryAccount + ) public initializer { __Ownable_init(); __ReentrancyGuard_init(); - - BitToken = _bitToken; + underlyingToken = IERC20(_bitToken); tssGroupContract = _tssGroupContract; + tssDelegationManagerContract = _delegationManager; + tssDelegationContract = _delegation; + //initialize delegation + delegationManager = IDelegationManager(_delegationManager); + delegation = IDelegation(_delegation); + messenger = _l1messenger; + regulatoryAccount = _regulatoryAccount; } /** * @notice change the bit token and tssGroup contract address * @param _token the erc20 bit token contract address - * @param _tssGroup tssGroup contract address */ - function setAddress(address _token, address _tssGroup) public onlyOwner { - BitToken = _token; + function setTokenAddress(address _token) public onlyOwner { + underlyingToken = IERC20(_token); + } + + function setTssGroupAddress(address _tssGroup) public onlyOwner{ tssGroupContract = _tssGroup; } + function setRegulatoryAccount(address _account) public onlyOwner { + regulatoryAccount = _account; + } + + function setPublicKey(bytes calldata _pubKey) public nonReentrant { + require(delegation.isOperator(msg.sender),"msg sender has not registered operator"); + operators[msg.sender] = _pubKey; + + } + + function setClaimer( + address staker, + address claimer + ) external { + require(msg.sender == staker, "msg sender is not the staker"); + require(delegation.isDelegated(staker),"msg sender has not delegated"); + + bytes memory message = abi.encodeWithSelector( + ITssRewardContract.setClaimer.selector, + staker, + claimer + ); + // send call data into L2, hardcode address + sendCrossDomainMessage( + address(0x4200000000000000000000000000000000000020), + 2000000, + message + ); + } + /** * @notice set the slashing params (0 -> uptime , 1 -> animus) * @param _slashAmount the amount to be deducted for each type - * @param _exIncome additional amount available to the originator of the report */ - function setSlashingParams(uint256[2] calldata _slashAmount, uint256[2] calldata _exIncome) + function setSlashingParams(uint256[2] calldata _slashAmount) public onlyOwner { require(_slashAmount[1] > _slashAmount[0], "invalid param slashAmount, animus <= uptime"); - require(_exIncome[1] > _exIncome[0], "invalid param exIncome, animus <= uptime"); for (uint256 i = 0; i < 2; i++) { - require(_exIncome[i] > 0, "invalid amount"); - require(_slashAmount[i] > _exIncome[i], "slashAmount need bigger than exIncome"); + require(_slashAmount[i] > 0, "invalid amount"); slashAmount[i] = _slashAmount[i]; - exIncome[i] = _exIncome[i]; } } /** * @notice set the slashing params (0 -> uptime, 1 -> animus) - * @return _slashAmount the amount to be deducted for each type - */ - function getSlashingParams() public view returns (uint256[2] memory, uint256[2] memory) { - return (slashAmount, exIncome); - } - - /** - * @notice staking entrance for user to deposit bit tokens - * @param _amount deposit amount of bit token - * @param _pubKey public key of sender */ - function staking(uint256 _amount, bytes calldata _pubKey) public nonReentrant { - // slashing params check - for (uint256 i = 0; i < 2; i++) { - require(slashAmount[i] > 0, "have not set the slash amount"); - require(exIncome[i] > 0, "have not set the extra income amount"); - } - // verify amount - require(_amount > 0, "invalid amount"); - require( - deposits[msg.sender].amount + _amount >= slashAmount[1], - "need deposit >= slashAmount" - ); - - if (deposits[msg.sender].pubKey.length > 0) { - // increase pledge amount - require(isEqual(deposits[msg.sender].pubKey, _pubKey), "pubKey not equal"); - } else { - // new to staking - require( - msg.sender == ITssGroupManager(tssGroupContract).publicKeyToAddress(_pubKey), - "invalid pubKey" - ); - deposits[msg.sender].pubKey = _pubKey; - deposits[msg.sender].pledgor = msg.sender; - } - - // send bit token to staking contract, need user approve first - require( - IERC20(BitToken).transferFrom(msg.sender, address(this), _amount), - "transfer erc20 token failed" - ); - deposits[msg.sender].amount += _amount; - - emit AddDeposit( - msg.sender, - DepositInfo({ pledgor: msg.sender, pubKey: _pubKey, amount: _amount }) - ); + function getSlashingParams() public view returns (uint256[2] memory) { + return slashAmount; } - /** - * @notice user who not elected to be validator to withdraw their bit token - */ - function withdrawToken() public nonReentrant { - uint256 amount = deposits[msg.sender].amount; - require(amount > 0, "do not have deposit"); - bytes memory pubKey = deposits[msg.sender].pubKey; - - // when not in consensus period or be selected - require( - !ITssGroupManager(tssGroupContract).memberExistInActive(pubKey) && - !ITssGroupManager(tssGroupContract).memberExistActive(pubKey), - "not at the right time" - ); - - delete deposits[msg.sender]; - - require(IERC20(BitToken).transfer(msg.sender, amount), "erc20 transfer failed"); - emit Withdraw(msg.sender, amount); - } /** * @notice send quit request for the next election */ function quitRequest() public nonReentrant { - require(deposits[msg.sender].amount > 0, "do not have deposit"); + + require(delegation.operatorShares(msg.sender, this) > 0, "do not have deposit"); // when not in consensus period require( - ITssGroupManager(tssGroupContract).memberExistInActive(deposits[msg.sender].pubKey) || - ITssGroupManager(tssGroupContract).memberExistActive(deposits[msg.sender].pubKey), + ITssGroupManager(tssGroupContract).memberExistInActive(operators[msg.sender]) || + ITssGroupManager(tssGroupContract).memberExistActive(operators[msg.sender]), "not at the inactive group or active group" ); // is active member @@ -244,74 +242,62 @@ contract TssStakingSlashing is // slashing params check for (uint256 i = 0; i < 2; i++) { require(slashAmount[i] > 0, "have not set the slash amount"); - require(exIncome[i] > 0, "have not set the extra income amount"); } - bytes memory jailNodePubKey = deposits[message.jailNode].pubKey; + bytes memory jailNodePubKey = operators[message.jailNode]; if (message.slashType == SlashType.uptime) { // jail and transfer deposits ITssGroupManager(tssGroupContract).memberJail(jailNodePubKey); - transformDeposit(message.jailNode, 0, message.tssNodes); + transformDeposit(message.jailNode, 0); } else if (message.slashType == SlashType.animus) { // remove the member and transfer deposits - ITssGroupManager(tssGroupContract).removeMember(jailNodePubKey); - transformDeposit(message.jailNode, 1, message.tssNodes); + ITssGroupManager(tssGroupContract).memberJail(jailNodePubKey); + transformDeposit(message.jailNode, 1); } else { require(false, "err type for slashing"); } + } /** * @notice distribute rewards to voters * @param deduction address of the punished * @param slashType the type to punished - * @param tssNodes participants other than the initiator */ function transformDeposit( address deduction, - uint256 slashType, - address[] memory tssNodes + uint256 slashType ) internal { - uint256 deductedAmount; - uint256 totalTransfer; - uint256 extraAmount; - uint256 remainder; - uint256 gain; - uint256 _exIncome = 0; - // total slash slashAmount[slashType] - // tssnodes get: gain = (slashAmount[slashType] - exIncome[slashType]) / tssnodes.length - // sender get: remainder + _exIncome = (slashAmount[slashType] - exIncome[slashType]) % tssnodes.length + exIncome[slashType] - // deductedAmount = tssnodes.length * gain + remainder + _exIncome = slashAmount[slashType] - - // check deposit > slashAmount, deduct slashAmount then - // distribute additional tokens for the sender + uint256 deductedAmountShare; + + uint256 totalBalance = _tokenBalance(); + require( - deposits[deduction].amount >= slashAmount[slashType], - "do not have enought deposit" + (delegation.operatorShares(deduction, this) * totalBalance) / totalShares >= slashAmount[slashType], + "do not have enought shares" ); // record total penalty - deductedAmount = slashAmount[slashType]; - // record the sender's fixed additional income - _exIncome = exIncome[slashType]; - - // deal with the punished - deposits[deduction].amount -= deductedAmount; - // record the deserving income for tss nodes - extraAmount = deductedAmount - _exIncome; - // deserving income should subtract the remainder - remainder = extraAmount % tssNodes.length; - // record the gain for tss nodes - gain = (extraAmount - remainder) / tssNodes.length; - - // sender get the fixed additional income and remainder - deposits[msg.sender].amount += _exIncome + remainder; - totalTransfer = exIncome[slashType] + remainder; - // send gain to tss nodes - for (uint256 i = 0; i < tssNodes.length; i++) { - totalTransfer += gain; - deposits[tssNodes[i]].amount += gain; + deductedAmountShare = (slashAmount[slashType] * totalShares) / totalBalance; + + uint256 operatorShare = delegation.operatorShares(deduction, this); + + IDelegationShare[] memory delegationShares = new IDelegationShare[](1); + delegationShares[0] = this; + + uint256[] memory delegationShareIndexes = new uint256[](1); + delegationShareIndexes[0] = 0; + + + IERC20[] memory tokens = new IERC20[](1); + tokens[0] = underlyingToken; + + address[] memory stakerS = stakers[deduction]; + for (uint256 i = 0; i < stakerS.length; i++){ + uint256 share = shares(stakerS[i]); + uint256[] memory shareAmounts = new uint256[](1); + shareAmounts[0] = deductedAmountShare * share / operatorShare; + TssDelegationManager(tssDelegationManagerContract).slashShares(deduction, regulatoryAccount, delegationShares,tokens, delegationShareIndexes, shareAmounts); } - // The total transfer amount is the same as the deducted amount - require(totalTransfer == deductedAmount, "panic, calculation error"); + } /** @@ -321,32 +307,15 @@ contract TssStakingSlashing is // slashing params check for (uint256 i = 0; i < 2; i++) { require(slashAmount[i] > 0, "have not set the slash amount"); - require(exIncome[i] > 0, "have not set the extra income amount"); } - require(deposits[msg.sender].amount >= slashAmount[1], "Insufficient balance"); - ITssGroupManager(tssGroupContract).memberUnJail(deposits[msg.sender].pubKey); - } - /** - * @notice get the deposit info - * @param user address of the staker - */ - function getDeposits(address user) public view returns (DepositInfo memory) { - return deposits[user]; - } + uint256 totalBalance = _tokenBalance(); - /** - * @notice get the deposit infos - * @param users address list of the stakers - */ - function batchGetDeposits(address[] calldata users) public view returns (DepositInfo[] memory) { - DepositInfo[] memory depositsList = new DepositInfo[](users.length); - for (uint256 i = 0; i < users.length; i++) { - depositsList[i] = deposits[users[i]]; - } - return depositsList; + require((delegation.operatorShares(msg.sender, this) * totalBalance) / totalShares >= slashAmount[1], "Insufficient balance"); + ITssGroupManager(tssGroupContract).memberUnJail(operators[msg.sender]); } + /** * @notice get the slash record * @param batchIndex the index of batch @@ -362,7 +331,7 @@ contract TssStakingSlashing is */ function isJailed(address user) public returns (bool) { ITssGroupManager.TssMember memory tssMember = ITssGroupManager(tssGroupContract) - .getTssMember(deposits[user].pubKey); + .getTssMember(operators[user]); require(tssMember.publicKey.length == 64, "tss member not exist"); return tssMember.status == ITssGroupManager.MemberStatus.jail; } @@ -377,4 +346,131 @@ contract TssStakingSlashing is } return true; } + + function isCanOperator(address _addr) public returns (bool) { + return TssDelegationManager(tssDelegationManagerContract).isCanOperator(_addr, this); + } + + function deposit(uint256 amount) public returns (uint256) { + uint256 shares = TssDelegationManager(tssDelegationManagerContract).depositInto(this, underlyingToken, amount, msg.sender); + return shares; + } + + function withdraw() external { + require(delegation.isDelegated(msg.sender),"not delegator"); + + require( + withdrawalRoots[msg.sender] == bytes32(0), + "msg sender already request withdraws" + ); + + uint256[] memory delegationIndexes = new uint256[](1); + delegationIndexes[0] = 0; + IDelegationShare[] memory delegationShares = new IDelegationShare[](1); + delegationShares[0] = this; + IERC20[] memory tokens = new IERC20[](1); + tokens[0] = underlyingToken; + uint256[] memory sharesA = new uint256[](1); + sharesA[0] = shares(msg.sender); + uint256 nonce = TssDelegationManager(tssDelegationManagerContract).getWithdrawNonce(msg.sender); + IDelegationManager.WithdrawerAndNonce memory withdrawerAndNonce = IDelegationManager.WithdrawerAndNonce({ + withdrawer: msg.sender, + nonce: SafeCast.toUint96(nonce) + }); + address operator = delegation.delegatedTo(msg.sender); + + IDelegationManager.QueuedWithdrawal memory queuedWithdrawal = IDelegationManager.QueuedWithdrawal({ + delegations: delegationShares, + tokens: tokens, + shares: sharesA, + depositor: msg.sender, + withdrawerAndNonce: withdrawerAndNonce, + delegatedAddress: operator + }); + withdrawals[msg.sender] = queuedWithdrawal; + bytes32 withdrawRoot = TssDelegationManager(tssDelegationManagerContract).queueWithdrawal(msg.sender,delegationIndexes,delegationShares,tokens,sharesA,withdrawerAndNonce); + withdrawalRoots[msg.sender] = withdrawRoot; + emit WithdrawQueue(msg.sender, sharesA[0]); + } + + function startWithdraw() external { + require( + withdrawalRoots[msg.sender] != bytes32(0), + "msg sender must request withdraw first" + ); + bytes32 withdrawRoot = withdrawalRoots[msg.sender]; + TssDelegationManager(tssDelegationManagerContract).startQueuedWithdrawalWaitingPeriod(withdrawRoot,msg.sender,0); + } + + function canCompleteQueuedWithdrawal() external returns (bool) { + + require( + withdrawalRoots[msg.sender] != bytes32(0), + "msg sender did not request withdraws" + ); + IDelegationManager.QueuedWithdrawal memory queuedWithdrawal = withdrawals[msg.sender]; + return delegationManager.canCompleteQueuedWithdrawal(queuedWithdrawal); + } + + function completeWithdraw() external { + + require( + withdrawalRoots[msg.sender] != bytes32(0), + "msg sender did not request withdraws" + ); + IDelegationManager.QueuedWithdrawal memory queuedWithdrawal = withdrawals[msg.sender]; + require(delegationManager.canCompleteQueuedWithdrawal(queuedWithdrawal),"The waiting period has not yet passed"); + TssDelegationManager(tssDelegationManagerContract).completeQueuedWithdrawal(msg.sender, queuedWithdrawal, true); + delete withdrawalRoots[msg.sender]; + delete withdrawals[msg.sender]; + } + + function registerAsOperator(bytes calldata _pubKey) external { + TssDelegation(tssDelegationContract).registerAsOperator(this, msg.sender); + setPublicKey(_pubKey); + } + + function delegateTo(address _operator) external { + TssDelegation(tssDelegationContract).delegateTo(_operator, msg.sender); + } + + + function onDelegationReceived( + address delegator, + address operator, + IDelegationShare[] memory delegationShares, + uint256[] memory investorShares + )external override onlyDelegation { + uint256 delegationLength = delegationShares.length; + require(delegationLength == 1,"delegation only for tss"); + require(investorShares.length == 1,"delegation share only for tss"); + require(address(delegationShares[0]) == address(this),"must use current contract"); + if (delegators[delegator] == address(0)) { + delegators[delegator] = operator; + stakers[operator].push(delegator); + } + } + + function onDelegationWithdrawn( + address delegator, + address operator, + IDelegationShare[] memory delegationShares, + uint256[] memory investorShares + ) external override onlyDelegation { + uint256 delegationLength = delegationShares.length; + require(delegationLength == 1,"delegation only for tss"); + require(investorShares.length == 1,"delegation share only for tss"); + require(address(delegationShares[0]) == address(this),"must use current contract"); + if (TssDelegationManager(tssDelegationManagerContract).getDelegationShares(delegator, delegationShares[0]) == investorShares[0]){ + address[] memory staker = stakers[operator]; + for (uint256 j = 0; j < staker.length; j++) { + if (staker[j] == delegator) { + stakers[operator][j] = stakers[operator][staker.length -1]; + stakers[operator].pop(); + delete delegators[delegator]; + } + } + } + } + } diff --git a/packages/contracts/contracts/L1/tss/delegation/TssDelegation.sol b/packages/contracts/contracts/L1/tss/delegation/TssDelegation.sol new file mode 100644 index 000000000..89d0027b2 --- /dev/null +++ b/packages/contracts/contracts/L1/tss/delegation/TssDelegation.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import "../../delegation/Delegation.sol"; +import "../../delegation/WhiteListBase.sol"; + + +/** + * @title The primary delegation contract. + * @notice This is the contract for delegation. The main functionalities of this contract are + * - for enabling any staker to register as a delegate and specify the delegation terms it has agreed to + * - for enabling anyone to register as an operator + * - for a registered staker to delegate its stake to the operator of its agreed upon delegation terms contract + * - for a staker to undelegate its assets + * - for anyone to challenge a staker's claim to have fulfilled all its obligation before undelegation + */ +contract TssDelegation is Delegation { + + + address public stakingSlash; + + + + + // INITIALIZING FUNCTIONS + constructor(IDelegationManager _delegationManager) + Delegation(_delegationManager) + { + _disableInitializers(); + } + + + function initializeT( + address _stakingSlashing, + address initialOwner + ) external initializer { + DOMAIN_SEPARATOR = keccak256(abi.encode(DOMAIN_TYPEHASH, bytes("Mantle"), block.chainid, address(this))); + stakingSlash = _stakingSlashing; + _transferOwnership(initialOwner); + } + + modifier onlyStakingSlash() { + require(msg.sender == stakingSlash, "contract call is not staking slashing"); + _; + } + + function setStakingSlash(address _address) public onlyOwner { + stakingSlash = _address; + } + + function registerAsOperator(IDelegationCallback dt, address sender) external whitelistOnly(sender) onlyStakingSlash { + + require( + address(delegationCallback[sender]) == address(0), + "Delegation.registerAsOperator: Delegate has already registered" + ); + // store the address of the delegation contract that the operator is providing. + delegationCallback[sender] = dt; + _delegate(sender, sender); + emit RegisterOperator(address(dt), sender); + } + + function delegateTo(address operator, address staker) external onlyStakingSlash whenNotPaused { + _delegate(staker, operator); + } + + +} diff --git a/packages/contracts/contracts/L1/tss/delegation/TssDelegationManager.sol b/packages/contracts/contracts/L1/tss/delegation/TssDelegationManager.sol new file mode 100644 index 000000000..30feffa05 --- /dev/null +++ b/packages/contracts/contracts/L1/tss/delegation/TssDelegationManager.sol @@ -0,0 +1,412 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import "../../delegation/DelegationManager.sol"; +import "../ITssGroupManager.sol"; +import "../TssStakingSlashing.sol"; + + +/** + * @title The primary entry- and exit-point for funds into and out. + * @notice This contract is for managing investments in different strategies. The main + * functionalities are: + * - adding and removing investment strategies that any delegator can invest into + * - enabling deposit of assets into specified investment delegation(s) + * - enabling removal of assets from specified investment delegation(s) + * - recording deposit of ETH into settlement layer + * - recording deposit for securing + * - slashing of assets for permissioned strategies + */ +contract TssDelegationManager is DelegationManager { + + + address public stakingSlash; + address public tssGroupManager; + + uint256 public minStakeAmount; + + + /** + * @param _delegation The delegation contract. + * @param _delegationSlasher The primary slashing contract. + */ + constructor(IDelegation _delegation, IDelegationSlasher _delegationSlasher) + DelegationManager(_delegation, _delegationSlasher) + { + _disableInitializers(); + } + + function initializeT( + address _stakingSlashing, + address _tssGroupManager, + uint256 _minStakeAmount, + address initialOwner + ) public initializer { + DOMAIN_SEPARATOR = keccak256(abi.encode(DOMAIN_TYPEHASH, bytes("Mantle"), block.chainid, address(this))); + _transferOwnership(initialOwner); + stakingSlash = _stakingSlashing; + tssGroupManager = _tssGroupManager; + minStakeAmount = _minStakeAmount; + } + + + modifier onlyStakingSlash() { + require(msg.sender == stakingSlash, "contract call is not staking slashing"); + _; + } + + function setStakingSlash(address _address) public onlyOwner { + stakingSlash = _address; + } + + function setMinStakeAmount(uint256 _amount) public onlyOwner { + minStakeAmount = _amount; + } + + function setTssGroupManager(address _addr) public onlyOwner { + tssGroupManager = _addr; + } + + /** + * @notice Slashes the shares of a 'frozen' operator (or a staker delegated to one) + * @param slashedAddress is the frozen address that is having its shares slashed + * @param delegationIndexes is a list of the indices in `investorStrats[msg.sender]` that correspond to the strategies + * for which `msg.sender` is withdrawing 100% of their shares + * @param recipient The slashed funds are withdrawn as tokens to this address. + * @dev delegationShares are removed from `investorStrats` by swapping the last entry with the entry to be removed, then + * popping off the last entry in `investorStrats`. The simplest way to calculate the correct `delegationIndexes` to input + * is to order the strategies *for which `msg.sender` is withdrawing 100% of their shares* from highest index in + * `investorStrats` to lowest index + */ + function slashShares( + address slashedAddress, + address recipient, + IDelegationShare[] calldata delegationShares, + IERC20[] calldata tokens, + uint256[] calldata delegationIndexes, + uint256[] calldata shareAmounts + ) + external + override + whenNotPaused + onlyStakingSlash + nonReentrant + { + + uint256 delegationIndex; + uint256 strategiesLength = delegationShares.length; + for (uint256 i = 0; i < strategiesLength;) { + // the internal function will return 'true' in the event the delegation contract was + // removed from the slashedAddress's array of strategies -- i.e. investorStrats[slashedAddress] + if (_removeShares(slashedAddress, delegationIndexes[delegationIndex], delegationShares[i], shareAmounts[i])) { + unchecked { + ++delegationIndex; + } + } + + // withdraw the shares and send funds to the recipient + delegationShares[i].withdraw(recipient, tokens[i], shareAmounts[i]); + + // increment the loop + unchecked { + ++i; + } + } + + // modify delegated shares accordingly, if applicable + delegation.decreaseDelegatedShares(slashedAddress, delegationShares, shareAmounts); + } + + function queueWithdrawal( + uint256[] calldata delegationIndexes, + IDelegationShare[] calldata delegationShares, + IERC20[] calldata tokens, + uint256[] calldata shares, + WithdrawerAndNonce calldata withdrawerAndNonce, + bool undelegateIfPossible + ) + external + override + whenNotPaused + onlyNotFrozen(msg.sender) + nonReentrant + returns (bytes32) + { + require( + withdrawerAndNonce.nonce == numWithdrawalsQueued[msg.sender], + "InvestmentManager.queueWithdrawal: provided nonce incorrect" + ); + require(delegationShares.length == 1, "only tss delegation share"); + require(shares.length == 1,"only tss delegation share"); + // increment the numWithdrawalsQueued of the sender + unchecked { + ++numWithdrawalsQueued[msg.sender]; + } + _checkMinStakeAmount(msg.sender,delegationShares[0],shares[0]); + + uint256 delegationIndex; + + // modify delegated shares accordingly, if applicable + delegation.decreaseDelegatedShares(msg.sender, delegationShares, shares); + + for (uint256 i = 0; i < delegationShares.length;) { + // the internal function will return 'true' in the event the delegation contrat was + // removed from the depositor's array of strategies -- i.e. investorStrats[depositor] + if (_removeShares(msg.sender, delegationIndexes[delegationIndex], delegationShares[i], shares[i])) { + unchecked { + ++delegationIndex; + } + } + + //increment the loop + unchecked { + ++i; + } + } + + // fetch the address that the `msg.sender` is delegated to + address delegatedAddress = delegation.delegatedTo(msg.sender); + + // copy arguments into struct and pull delegation info + QueuedWithdrawal memory queuedWithdrawal = QueuedWithdrawal({ + delegations: delegationShares, + tokens: tokens, + shares: shares, + depositor: msg.sender, + withdrawerAndNonce: withdrawerAndNonce, + delegatedAddress: delegatedAddress + }); + + // calculate the withdrawal root + bytes32 withdrawalRoot = calculateWithdrawalRoot(queuedWithdrawal); + + //update storage in mapping of queued withdrawals + queuedWithdrawals[withdrawalRoot] = WithdrawalStorage({ + /** + * @dev We add `REASONABLE_STAKES_UPDATE_PERIOD` to the current time here to account for the fact that it may take some time for + * the operator's stake to be updated on all the middlewares. New tasks created between now at this 'initTimestamp' may still + * subject the `msg.sender` to slashing! + */ + initTimestamp: uint32(block.timestamp + REASONABLE_STAKES_UPDATE_PERIOD), + withdrawer: withdrawerAndNonce.withdrawer, + unlockTimestamp: QUEUED_WITHDRAWAL_INITIALIZED_VALUE + }); + + // If the `msg.sender` has withdrawn all of their funds in this transaction, then they can choose to also undelegate + /** + * Checking that `investorStrats[msg.sender].length == 0` is not strictly necessary here, but prevents reverting very late in logic, + * in the case that 'undelegate' is set to true but the `msg.sender` still has active deposits. + */ + if (undelegateIfPossible && investorDelegations[msg.sender].length == 0) { + _undelegate(msg.sender); + } + + emit WithdrawalQueued(msg.sender, withdrawerAndNonce.withdrawer, delegatedAddress, withdrawalRoot); + + return withdrawalRoot; + } + + + function isCanOperator(address _addr, IDelegationShare delegationShare) external returns (bool) { + if (delegation.isOperator(_addr)) { + uint256 share = delegation.operatorShares(_addr, delegationShare); + uint256 balance = delegationShare.sharesToUnderlying(share); + if (balance > minStakeAmount) { + return true; + } + } + return false; + } + + function depositInto(IDelegationShare delegationShare, IERC20 token, uint256 amount, address sender) + external + onlyNotFrozen(sender) + nonReentrant + whitelistOnly(address(delegationShare)) + onlyStakingSlash + returns (uint256 shares) + { + shares = _depositInto(sender, delegationShare, token, amount); + } + + function queueWithdrawal( + address sender, + uint256[] calldata delegationIndexes, + IDelegationShare[] calldata delegationShares, + IERC20[] calldata tokens, + uint256[] calldata shares, + WithdrawerAndNonce calldata withdrawerAndNonce + ) + external + whenNotPaused + onlyNotFrozen(sender) + onlyStakingSlash + nonReentrant + returns (bytes32) + { + require( + withdrawerAndNonce.nonce == numWithdrawalsQueued[sender], + "InvestmentManager.queueWithdrawal: provided nonce incorrect" + ); + require(delegationShares.length == 1, "only tss delegation share"); + require(shares.length == 1,"only tss delegation share"); + // increment the numWithdrawalsQueued of the sender + unchecked { + ++numWithdrawalsQueued[sender]; + } + address operator = delegation.delegatedTo(sender); + + _checkMinStakeAmount(sender, delegationShares[0], shares[0]); + + // modify delegated shares accordingly, if applicable + delegation.decreaseDelegatedShares(sender, delegationShares, shares); + + // the internal function will return 'true' in the event the delegation contrat was + // removed from the depositor's array of strategies -- i.e. investorStrats[depositor] + _removeShares(sender, delegationIndexes[0], delegationShares[0], shares[0]); + + // copy arguments into struct and pull delegation info + QueuedWithdrawal memory queuedWithdrawal = QueuedWithdrawal({ + delegations: delegationShares, + tokens: tokens, + shares: shares, + depositor: sender, + withdrawerAndNonce: withdrawerAndNonce, + delegatedAddress: operator + }); + + // calculate the withdrawal root + bytes32 withdrawalRoot = calculateWithdrawalRoot(queuedWithdrawal); + + //update storage in mapping of queued withdrawals + queuedWithdrawals[withdrawalRoot] = WithdrawalStorage({ + /** + * @dev We add `REASONABLE_STAKES_UPDATE_PERIOD` to the current time here to account for the fact that it may take some time for + * the operator's stake to be updated on all the middlewares. New tasks created between now at this 'initTimestamp' may still + * subject the `msg.sender` to slashing! + */ + initTimestamp: uint32(block.timestamp + REASONABLE_STAKES_UPDATE_PERIOD), + withdrawer: withdrawerAndNonce.withdrawer, + unlockTimestamp: QUEUED_WITHDRAWAL_INITIALIZED_VALUE + }); + + address staker = sender; + // If the `msg.sender` has withdrawn all of their funds in this transaction, then they can choose to also undelegate + /** + * Checking that `investorStrats[msg.sender].length == 0` is not strictly necessary here, but prevents reverting very late in logic, + * in the case that 'undelegate' is set to true but the `msg.sender` still has active deposits. + */ + if (investorDelegations[staker].length == 0) { + _undelegate(staker); + } + + emit WithdrawalQueued(staker, withdrawerAndNonce.withdrawer, operator, withdrawalRoot); + + return withdrawalRoot; + } + + + function startQueuedWithdrawalWaitingPeriod(bytes32 withdrawalRoot, address sender, uint32 stakeInactiveAfter) external onlyStakingSlash { + require( + queuedWithdrawals[withdrawalRoot].unlockTimestamp == QUEUED_WITHDRAWAL_INITIALIZED_VALUE, + "InvestmentManager.startQueuedWithdrawalWaitingPeriod: Withdrawal stake inactive claim has already been made" + ); + require( + queuedWithdrawals[withdrawalRoot].withdrawer == sender, + "InvestmentManager.startQueuedWithdrawalWaitingPeriod: Sender is not the withdrawer" + ); + require( + block.timestamp > queuedWithdrawals[withdrawalRoot].initTimestamp, + "InvestmentManager.startQueuedWithdrawalWaitingPeriod: Stake may still be subject to slashing based on new tasks. Wait to set stakeInactiveAfter." + ); + //they can only unlock after a withdrawal waiting period or after they are claiming their stake is inactive + queuedWithdrawals[withdrawalRoot].unlockTimestamp = max((uint32(block.timestamp) + WITHDRAWAL_WAITING_PERIOD), stakeInactiveAfter); + } + + function completeQueuedWithdrawal(address sender, QueuedWithdrawal calldata queuedWithdrawal, bool receiveAsTokens) + external + whenNotPaused + // check that the address that the staker *was delegated to* – at the time that they queued the withdrawal – is not frozen + onlyNotFrozen(queuedWithdrawal.delegatedAddress) + nonReentrant + onlyStakingSlash + { + // find the withdrawalRoot + bytes32 withdrawalRoot = calculateWithdrawalRoot(queuedWithdrawal); + // copy storage to memory + WithdrawalStorage memory withdrawalStorageCopy = queuedWithdrawals[withdrawalRoot]; + + // verify that the queued withdrawal actually exists + require( + withdrawalStorageCopy.unlockTimestamp != 0, + "InvestmentManager.completeQueuedWithdrawal: withdrawal does not exist" + ); + + require( + uint32(block.timestamp) >= withdrawalStorageCopy.unlockTimestamp + || (queuedWithdrawal.delegatedAddress == address(0)), + "InvestmentManager.completeQueuedWithdrawal: withdrawal waiting period has not yet passed and depositor was delegated when withdrawal initiated" + ); + + // TODO: add testing coverage for this + require( + sender == queuedWithdrawal.withdrawerAndNonce.withdrawer, + "InvestmentManager.completeQueuedWithdrawal: only specified withdrawer can complete a queued withdrawal" + ); + + // reset the storage slot in mapping of queued withdrawals + delete queuedWithdrawals[withdrawalRoot]; + + // store length for gas savings + uint256 strategiesLength = queuedWithdrawal.delegations.length; + // if the withdrawer has flagged to receive the funds as tokens, withdraw from strategies + if (receiveAsTokens) { + // actually withdraw the funds + for (uint256 i = 0; i < strategiesLength;) { + // tell the delegation to send the appropriate amount of funds to the depositor + queuedWithdrawal.delegations[i].withdraw( + withdrawalStorageCopy.withdrawer, queuedWithdrawal.tokens[i], queuedWithdrawal.shares[i] + ); + unchecked { + ++i; + } + } + } else { + // else increase their shares + for (uint256 i = 0; i < strategiesLength;) { + _addShares(withdrawalStorageCopy.withdrawer, queuedWithdrawal.delegations[i], queuedWithdrawal.shares[i]); + unchecked { + ++i; + } + } + } + + emit WithdrawalCompleted(queuedWithdrawal.depositor, withdrawalStorageCopy.withdrawer, withdrawalRoot); + } + + function getWithdrawNonce(address staker) external view onlyStakingSlash returns (uint256) { + return numWithdrawalsQueued[staker]; + } + + function getDelegationShares(address staker,IDelegationShare delegationShare) external view onlyStakingSlash returns (uint256) { + return investorDelegationShares[staker][delegationShare]; + } + + function _checkMinStakeAmount(address sender,IDelegationShare delegationShare, uint256 shares) internal { + address operator = delegation.delegatedTo(sender); + // check if the operator is still mpc node, if the remaining shares meet the mini requirement + if (delegation.isDelegated(sender)){ + if (ITssGroupManager(tssGroupManager).memberExistActive(sender)){ + require(!TssStakingSlashing(stakingSlash).isJailed(operator),"the operator is not in jail status"); + uint256 rest= delegation.operatorShares(operator, delegationShare) - shares; + uint256 balance = delegationShare.sharesToUnderlying(rest); + if (ITssGroupManager(tssGroupManager).isTssGroupUnJailMembers(operator)) { + require(balance > minStakeAmount,"unable withdraw due to operator's rest shares smaller than mini requirement"); + } + } + } + } + + +} + diff --git a/packages/contracts/contracts/L1/tss/delegation/TssDelegationSlasher.sol b/packages/contracts/contracts/L1/tss/delegation/TssDelegationSlasher.sol new file mode 100644 index 000000000..5630b1098 --- /dev/null +++ b/packages/contracts/contracts/L1/tss/delegation/TssDelegationSlasher.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +import "../../delegation/DelegationSlasher.sol"; + +/** + * @title The primary 'slashing' contract. + * @notice This contract specifies details on slashing. The functionalities are: + * - adding contracts who have permission to perform slashing, + * - revoking permission for slashing from specified contracts, + * - calling investManager to do actual slashing. + */ +contract TssDelegationSlasher is DelegationSlasher { + constructor(IDelegationManager _delegationManager, IDelegation _delegation) + DelegationSlasher(_delegationManager, _delegation) + { + _disableInitializers(); + } +} diff --git a/packages/contracts/contracts/L2/predeploys/TssRewardContract.sol b/packages/contracts/contracts/L2/predeploys/TssRewardContract.sol index 9e6104177..5696483dc 100644 --- a/packages/contracts/contracts/L2/predeploys/TssRewardContract.sol +++ b/packages/contracts/contracts/L2/predeploys/TssRewardContract.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.9; import {ITssRewardContract} from "./iTssRewardContract.sol"; import {IBVM_GasPriceOracle} from "./iBVM_GasPriceOracle.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {Lib_PredeployAddresses} from "../../libraries/constants/Lib_PredeployAddresses.sol"; import { CrossDomainEnabled } from "../../libraries/bridge/CrossDomainEnabled.sol"; @@ -31,10 +32,24 @@ contract TssRewardContract is Ownable,ITssRewardContract,CrossDomainEnabled { uint256 public sendAmountPerYear; address public sccAddress; + uint256 public dustBlock; + uint256 public waitingTime; + // operator => tssreward + mapping(address => uint256) public rewardDetails; + //operator => claimer + mapping(address => address) public operators; + //claimer => operator + mapping(address => address) public claimers; + //operator => timestamp + mapping(address => uint256) public claimTimes; + //operator => claim number + mapping(address => uint256) public claimAmout; + using SafeERC20 for IERC20; + IERC20 public rewardToken; // set call address - constructor(address _deadAddress, address _owner, uint256 _sendAmountPerYear, address _bvmGasPriceOracleAddress,address _l2CrossDomainMessenger, address _sccAddress) + constructor(address _deadAddress, address _owner, uint256 _sendAmountPerYear, address _bvmGasPriceOracleAddress,address _l2CrossDomainMessenger, address _sccAddress, uint256 _waitingTime, address _token) Ownable() CrossDomainEnabled(_l2CrossDomainMessenger) { transferOwnership(_owner); @@ -42,6 +57,8 @@ contract TssRewardContract is Ownable,ITssRewardContract,CrossDomainEnabled { sendAmountPerYear = _sendAmountPerYear; bvmGasPriceOracleAddress = _bvmGasPriceOracleAddress; sccAddress = _sccAddress; + waitingTime = _waitingTime; + rewardToken = IERC20(_token); } // slither-disable-next-line locked-ether @@ -67,10 +84,22 @@ contract TssRewardContract is Ownable,ITssRewardContract,CrossDomainEnabled { _; } + modifier onlyAuthorized() { + address operator = claimers[msg.sender]; + require(operator != address(0), + "The msg sender is not authorized by the validator" + ); + _; + } + function setSendAmountPerYear(uint256 _sendAmountPerYear) public onlyOwner { sendAmountPerYear = _sendAmountPerYear; } + function setWaitingTime(uint256 _waitingTime) public onlyOwner { + waitingTime = _waitingTime; + } + function querySendAmountPerSecond() public view returns (uint256){ return (sendAmountPerYear * 10 ** 18).div(365 * 24 * 60 * 60); } @@ -97,9 +126,7 @@ contract TssRewardContract is Ownable,ITssRewardContract,CrossDomainEnabled { claimRewardByBlock(_blockStartHeight, _length, _tssMembers); return; } - uint256 sendAmount = 0; uint256 batchAmount = 0; - uint256 accu = 0; // sendAmount if (lastBatchTime == 0) { lastBatchTime = _batchTime; @@ -108,20 +135,11 @@ contract TssRewardContract is Ownable,ITssRewardContract,CrossDomainEnabled { require(_batchTime > lastBatchTime,"args _batchTime must gther than last lastBatchTime"); batchAmount = (_batchTime - lastBatchTime) * querySendAmountPerSecond() + dust; dust = 0; - sendAmount = batchAmount.div(_tssMembers.length); - for (uint256 j = 0; j < _tssMembers.length; j++) { - address payable addr = payable(_tssMembers[j]); - accu = accu.add(sendAmount); - addr.transfer(sendAmount); - } - uint256 reserved = batchAmount.sub(accu); - if (reserved > 0) { - dust = dust.add(reserved); - } + _distributeReward(batchAmount, _tssMembers, false); emit DistributeTssReward( lastBatchTime, _batchTime, - sendAmount, + batchAmount, _tssMembers ); lastBatchTime = _batchTime; @@ -140,25 +158,15 @@ contract TssRewardContract is Ownable,ITssRewardContract,CrossDomainEnabled { uint256 batchAmount = 0; uint256 accu = 0; // release reward from _blockStartHeight to _blockStartHeight + _length - 1 - for (uint256 i = 0; i < _length; i++) { + for (uint i = 0; i < _length; i++) { batchAmount = batchAmount.add(ledger[_blockStartHeight + i]); // delete distributed height delete ledger[_blockStartHeight + i]; } if (batchAmount > 0) { - batchAmount = batchAmount + dust; - dust = 0; - sendAmount = batchAmount.div(_tssMembers.length); - for (uint256 j = 0; j < _tssMembers.length; j++) { - address payable addr = payable(_tssMembers[j]); - accu = accu.add(sendAmount); - totalAmount = totalAmount.sub(sendAmount); - addr.transfer(sendAmount); - } - uint256 reserved = batchAmount.sub(accu); - if (reserved > 0) { - dust = dust.add(reserved); - } + batchAmount = batchAmount + dustBlock; + dustBlock = 0; + _distributeReward(batchAmount, _tssMembers, true); } emit DistributeTssRewardByBlock( _blockStartHeight, @@ -189,14 +197,14 @@ contract TssRewardContract is Ownable,ITssRewardContract,CrossDomainEnabled { } /** - * @dev withdraw div dust + * @dev withdraw div dustBlock */ function withdrawDust() external onlyOwner checkBalance { - uint256 amount = dust; - totalAmount = totalAmount.sub(dust); - dust = 0; + uint256 amount = dustBlock; + totalAmount = totalAmount.sub(amount); + dustBlock = 0; if (amount > 0) { - payable(owner()).transfer(dust); + rewardToken.safeTransfer(owner(),amount); } } @@ -205,8 +213,103 @@ contract TssRewardContract is Ownable,ITssRewardContract,CrossDomainEnabled { */ function withdraw() external onlyOwner checkBalance { totalAmount = 0; - if (address(this).balance > 0) { - payable(owner()).transfer(address(this).balance); + uint256 balance = rewardToken.balanceOf(address(this)); + if (balance > 0) { + rewardToken.safeTransfer(owner(),balance); + } + } + + function requestClaim() external onlyAuthorized returns (bool) { + address operator = claimers[msg.sender]; + uint256 time = claimTimes[operator]; + require(time == 0, + "You have already initiated a request to claim, please wait for the waiting period to pass" + ); + claimTimes[operator] = block.timestamp; + claimAmout[operator] = rewardDetails[operator]; + return true; + } + + function queryClaimTime() external view onlyAuthorized returns (uint256) { + address operator = claimers[msg.sender]; + uint256 remainTime = _remainTime(operator); + return remainTime; + } + + /** + * @dev Claim reward + */ + function claim() external onlyAuthorized { + address operator = claimers[msg.sender]; + uint256 remainTime = _remainTime(operator); + require(remainTime == 0, + "please wait for the waiting period to pass" + ); + _claim(operator); + delete claimTimes[operator]; + } + + function setClaimer(address _operator, address _claimer) + external + virtual + onlyFromCrossDomainAccount(sccAddress) + { + claimers[_claimer] = _operator; + operators[_operator] = _claimer; + } + + function _remainTime(address operator) internal view returns (uint256) { + uint256 time = claimTimes[operator]; + require(time != 0, + "please initiate a request to claim first" + ); + uint256 last = time + waitingTime; + uint256 remaining; + if ( last > block.timestamp ) { + remaining = last - block.timestamp; + }else { + remaining = 0; + } + return remaining; + } + + + function _claim(address _operator) internal { + uint256 claimNumber = claimAmout[_operator]; + uint256 amount = rewardDetails[_operator]; + if (claimNumber > 0) { + address claimer = operators[_operator]; + rewardToken.safeTransfer(claimer,claimNumber); + delete claimAmout[_operator]; + rewardDetails[_operator] = rewardDetails[_operator] - claimNumber; } + emit Claim(_operator, amount); } + + function _distributeReward(uint256 amount, address[] calldata _tssMembers, bool isByBlock) internal { + if (amount > 0) { + uint256 sendAmount = 0; + uint256 accu = 0; + sendAmount = amount.div(_tssMembers.length); + for (uint i = 0; i < _tssMembers.length; i++) { + address operator = _tssMembers[i]; + rewardDetails[operator] += sendAmount; + accu = accu.add(sendAmount); + if (isByBlock) { + totalAmount = totalAmount.sub(sendAmount); + } + } + uint256 reserved = amount.sub(accu); + if (reserved > 0) { + if (isByBlock) { + dustBlock = dustBlock.add(reserved); + }else { + dust = dust.add(reserved); + } + + } + } + } + + } diff --git a/packages/contracts/contracts/L2/predeploys/iTssRewardContract.sol b/packages/contracts/contracts/L2/predeploys/iTssRewardContract.sol index 074160fb7..ff98c0aa1 100644 --- a/packages/contracts/contracts/L2/predeploys/iTssRewardContract.sol +++ b/packages/contracts/contracts/L2/predeploys/iTssRewardContract.sol @@ -24,6 +24,11 @@ interface ITssRewardContract { address[] tssMembers ); + event Claim( + address owner, + uint256 amount + ); + /******************** * Public Functions * ********************/ @@ -57,4 +62,27 @@ interface ITssRewardContract { * @dev clear contract(canonical). */ function withdraw() external; + + /** + * @dev Claim reward and withdraw + */ + function claim() external; + + /** + * @dev default claimer == staker, if staker is multi-signature address,must set claimer + * @param _staker the address of staker + * @param _claimer the address for staker to claim reward + */ + function setClaimer(address _staker, address _claimer) external; + + /** + * @dev Initiate a request to claim + */ + function requestClaim() external returns (bool); + + /** + * @dev Query the remaining time required to claim + */ + function queryClaimTime() external returns (uint256); + } diff --git a/packages/contracts/deploy/010-TssContracts.ts b/packages/contracts/deploy/010-TssContracts.ts index 1ec3dda5e..77b1aebcd 100644 --- a/packages/contracts/deploy/010-TssContracts.ts +++ b/packages/contracts/deploy/010-TssContracts.ts @@ -14,6 +14,141 @@ const deployFn: DeployFunction = async (hre) => { const owner = hre.deployConfig.bvmAddressManagerOwner const l1BitAddress = hre.deployConfig.l1BitAddress + let DelegationProxyAddress = "0xe6cd9e7b620964bECd42c7Ad41e56724f515E284" + let DelegationManagerProxyAddress = "0xE6A251EefaEE70E8645FBAdf21E9B1246e07C374" + let DelegationSlasherProxyAddress = "0xD007896d9E3e4514a1f1216A91d33a72e15bf5C0" + let StakingSlashingProxyAddress = "0x9c28c8D298ae7Ebf8daA6FA54e1F2909313dB158" + let TssGroupManagerProxyAddress = "0xF48398a3D94D57AE1406B343D2a7C541336Ea2c2" + + // deploy Delegation impl + await deployAndVerifyAndThen({ + hre, + name: names.managed.delegation.tss.TssDelegation, + contract: 'TssDelegation', + args: [DelegationManagerProxyAddress], + }) + const Impl__TssDelegation = await getContractFromArtifact( + hre, + names.managed.delegation.tss.TssDelegation, + { + iface: 'TssDelegation', + signerOrProvider: deployer, + } + ) + console.log('TssDelegation Implementation Address', Impl__TssDelegation.address) + console.log('deploy Tss Delegation success') + + // deploy DelegationManager impl + await deployAndVerifyAndThen({ + hre, + name: names.managed.delegation.tss.TssDelegationManager, + contract: 'TssDelegationManager', + args: [DelegationProxyAddress, DelegationSlasherProxyAddress], + }) + const Impl__TssDelegationManager = await getContractFromArtifact( + hre, + names.managed.delegation.tss.TssDelegationManager, + { + iface: 'TssDelegationManager', + signerOrProvider: deployer, + } + ) + console.log('TssDelegationManager Implementation Address', Impl__TssDelegationManager.address) + console.log('deploy Tss DelegationManager success') + + // deploy DelegationSlasher impl + await deployAndVerifyAndThen({ + hre, + name: names.managed.delegation.tss.TssDelegationSlasher, + contract: 'TssDelegationSlasher', + args: [DelegationManagerProxyAddress, DelegationProxyAddress], + }) + const Impl__TssDelegationSlasher = await getContractFromArtifact( + hre, + names.managed.delegation.tss.TssDelegationSlasher, + { + iface: 'TssDelegationSlasher', + signerOrProvider: deployer, + } + ) + console.log('Tss DelegationSlasher Implementation Address', Impl__TssDelegationSlasher.address) + console.log('deploy Tss DelegationSlasher success') + + // deploy Delegation proxy + let callData = Impl__TssDelegation.interface.encodeFunctionData( + 'initializeT', + [StakingSlashingProxyAddress, + deployer,] + ) + + await deployAndVerifyAndThen({ + hre, + name: names.managed.delegation.tss.Proxy__TssDelegation, + contract: 'TransparentUpgradeableProxy', + iface: 'TssDelegation', + args: [Impl__TssDelegation.address, owner, callData], + }) + const Proxy__TssDelegation = await getContractFromArtifact( + hre, + names.managed.delegation.tss.Proxy__TssDelegation, + { + iface: 'TssDelegation', + signerOrProvider: deployer, + } + ) + console.log('Proxy__TssDelegation Address', Proxy__TssDelegation.address) + console.log('deploy Tss Delegation Proxy__TssDelegation success') + + callData = Impl__TssDelegationSlasher.interface.encodeFunctionData( + 'initialize', + [deployer] + ) + await deployAndVerifyAndThen({ + hre, + name: names.managed.delegation.tss.Proxy__TssDelegationSlasher, + contract: 'TransparentUpgradeableProxy', + iface: 'TssDelegationSlasher', + args: [Impl__TssDelegationSlasher.address, owner, callData], + }) + + const Proxy__TssDelegationSlasher = await getContractFromArtifact( + hre, + names.managed.delegation.tss.Proxy__TssDelegationSlasher, + { + iface: 'TssDelegationSlasher', + signerOrProvider: deployer, + } + ) + console.log('Proxy__TssDelegationSlasher Address', Proxy__TssDelegationSlasher.address) + console.log('deploy Tss DelegationSlasher Proxy success') + + callData = Impl__TssDelegationManager.interface.encodeFunctionData( + 'initializeT', + [StakingSlashingProxyAddress, + TssGroupManagerProxyAddress, + '10000', + deployer, + ] + ) + await deployAndVerifyAndThen({ + hre, + name: names.managed.delegation.tss.Proxy__TssDelegationManager, + contract: 'TransparentUpgradeableProxy', + iface: 'TssDelegationManager', + args: [Impl__TssDelegationManager.address, owner, callData], + }) + + const Proxy__TssDelegationManager = await getContractFromArtifact( + hre, + names.managed.delegation.tss.Proxy__TssDelegationManager, + { + iface: 'TssDelegationManager', + signerOrProvider: deployer, + } + ) + console.log('Proxy__TssDelegationManager Address', Proxy__TssDelegationManager.address) + console.log('deploy Tss DelegationManager Proxy success') + // deploy impl await deployAndVerifyAndThen({ hre, @@ -52,7 +187,7 @@ const deployFn: DeployFunction = async (hre) => { let args: unknown[] args = [] - let callData = Impl_TSS_GroupManager.interface.encodeFunctionData( + callData = Impl_TSS_GroupManager.interface.encodeFunctionData( 'initialize', args ) @@ -74,11 +209,24 @@ const deployFn: DeployFunction = async (hre) => { } ) - args = [l1BitAddress, Proxy__TSS_GroupManager.address] + const Proxy__BVM_L1CrossDomainMessenger = await getContractFromArtifact( + hre, + names.managed.contracts.Proxy__BVM_L1CrossDomainMessenger + ) + + args = [ + l1BitAddress, + Proxy__TSS_GroupManager.address, + Proxy__TssDelegationManager.address, + Proxy__TssDelegation.address, + Proxy__BVM_L1CrossDomainMessenger.address, + owner, + ] callData = Impl__TssStakingSlashing.interface.encodeFunctionData( 'initialize', args ) + console.log('encode stakingslashing initialize calldata') await deployAndVerifyAndThen({ hre, name: names.managed.contracts.Proxy__TSS_StakingSlashing, @@ -92,7 +240,7 @@ const deployFn: DeployFunction = async (hre) => { return hexStringEquals( await contract .connect(Impl_TSS_GroupManager.signer.provider) - .BitToken({ from: ethers.constants.AddressZero }), + .underlyingToken({ from: ethers.constants.AddressZero }), l1BitAddress ) }, diff --git a/packages/contracts/filenames.txt b/packages/contracts/filenames.txt index 2e0e76d8e..4682426b1 100644 --- a/packages/contracts/filenames.txt +++ b/packages/contracts/filenames.txt @@ -1,18 +1,20 @@ Proxy__Verifier -FraudProofDelegationSlasher ChainStorageContainer-SCC-batches Proxy__AssertionMap BVM_EigenDataLayrFee StateCommitmentChain -Proxy__FraudProofDelegationSlasher TestBitToken +TssDelegationSlasher +TssDelegation ChainStorageContainer-CTC-batches Proxy__BVM_L1StandardBridge +Proxy__TssDelegationManager Rollup -Proxy__FraudProofDelegation TssStakingSlashing BVM_L1CrossDomainMessenger +Proxy__TssDelegation Proxy__TSS_GroupManager +Proxy__TssDelegationSlasher Proxy__BVM_EigenDataLayrFee Lib_AddressManager VerifierEntry @@ -20,10 +22,8 @@ AddressDictator BVM_EigenDataLayrChain CanonicalTransactionChain TssGroupManager -FraudProofDelegation L1StandardBridge_for_verification_only -Proxy__FraudProofDelegationManager -FraudProofDelegationManager +TssDelegationManager ChugSplashDictator Proxy__BVM_EigenDataLayrChain Proxy__BVM_L1CrossDomainMessenger diff --git a/packages/contracts/genesis/addresses.json b/packages/contracts/genesis/addresses.json index f891b927b..1f1d77aa8 100644 --- a/packages/contracts/genesis/addresses.json +++ b/packages/contracts/genesis/addresses.json @@ -1,36 +1,36 @@ { - "Proxy__Verifier": "0x4f958F2C2303BDca22b739339cD633F8543BB07D", - "FraudProofDelegationSlasher": "0x91dC1bd9704151B0Bc4cAD3BB5c24494188aA00B", + "Proxy__Verifier": "0x8eC353337d109C0f8eef2200021D28C542CAe8E6", "ChainStorageContainer-SCC-batches": "0x0090171f848B2aa86918E5Ef2406Ab3d424fdd83", - "Proxy__AssertionMap": "0x86E10B59cFDFeFBCf3ED5b40D018949CbFCE8B59", + "Proxy__AssertionMap": "0x88e7b36Ae38D502e4Df97e7240560B77F6B4a58E", "BVM_EigenDataLayrFee": "0x5BA7b75fE6fE4412713acc62EC3e9eA87e4B8282", "StateCommitmentChain": "0x8BAccFF561FDe61D6bC8B6f299fFBa561d2189B9", - "Proxy__FraudProofDelegationSlasher": "0x8eC353337d109C0f8eef2200021D28C542CAe8E6", "TestBitToken": "0x92aBAD50368175785e4270ca9eFd169c949C4ce1", + "TssDelegationSlasher": "0xa83239cf2b900682001f9144144B5E5e5788A631", + "TssDelegation": "0x82e130FF187E787D5DdDFAa4f36CB59e6B1Da6dd", "ChainStorageContainer-CTC-batches": "0x7A8B94a9fA2bb0581D2EEA2fEd875FCA97494612", "Proxy__BVM_L1StandardBridge": "0x52753615226F8aC8a464bfecb11Ef798CFF3793f", - "Rollup": "0x2eC3980EcddA68E073c39afD44909f8fe0fE3000", - "Proxy__FraudProofDelegation": "0x88e7b36Ae38D502e4Df97e7240560B77F6B4a58E", - "TssStakingSlashing": "0x36fCf02Fc651c0b7ef2ECA446Dd2405364F85337", + "Proxy__TssDelegationManager": "0xE6A251EefaEE70E8645FBAdf21E9B1246e07C374", + "Rollup": "0x91dC1bd9704151B0Bc4cAD3BB5c24494188aA00B", + "TssStakingSlashing": "0x7d0f87007795438DBCF67e4a91c03Bb3eDe152dE", "BVM_L1CrossDomainMessenger": "0xD076364Fa5de1a4512c58b39ad63DD720B7B9E11", - "Proxy__TSS_GroupManager": "0xa83239cf2b900682001f9144144B5E5e5788A631", + "Proxy__TssDelegation": "0xe6cd9e7b620964bECd42c7Ad41e56724f515E284", + "Proxy__TSS_GroupManager": "0xF48398a3D94D57AE1406B343D2a7C541336Ea2c2", + "Proxy__TssDelegationSlasher": "0xD007896d9E3e4514a1f1216A91d33a72e15bf5C0", "Proxy__BVM_EigenDataLayrFee": "0xeeC65aC2497dFE595b382132E0a35E73e93f2166", "Lib_AddressManager": "0x19C22f181280dF6Ad1d97285cdD430173Df91C12", - "VerifierEntry": "0x9109811E8eEe02520219612bB5D47C60c382F4aa", - "AddressDictator": "0xE6A251EefaEE70E8645FBAdf21E9B1246e07C374", - "BVM_EigenDataLayrChain": "0xc2E4F2038D456AfEFfF2351234BCaFCB6837baC1", + "VerifierEntry": "0x1eeAdb6C93161a34b2eBE9994fD73d6B7Bc70817", + "AddressDictator": "0xC346c14AA2c1001eee47CCEc1404D193ab1667Ab", + "BVM_EigenDataLayrChain": "0x4f958F2C2303BDca22b739339cD633F8543BB07D", "CanonicalTransactionChain": "0x9faB987C9C469EB23Da31B7848B28aCf30905eA8", - "TssGroupManager": "0x82e130FF187E787D5DdDFAa4f36CB59e6B1Da6dd", - "FraudProofDelegation": "0xb416faEaEf670632Db2Ad66558e74aaD6518FB84", - "L1StandardBridge_for_verification_only": "0xdf3BD218A936A92be5e43592143ecc7a33cef514", - "Proxy__FraudProofDelegationManager": "0x90c9E4f7F11C93BCec2e1F272b2063640d3bb264", - "FraudProofDelegationManager": "0x1eeAdb6C93161a34b2eBE9994fD73d6B7Bc70817", - "ChugSplashDictator": "0x18DF7d7Cc40928f07d3EF0e5404b41F97e8560Ad", - "Proxy__BVM_EigenDataLayrChain": "0x5a0069E211A28cBD1a7dbD585877596FeD07805b", + "TssGroupManager": "0x1FB27316e91e477943A87Eb215E40Fab6b382Fda", + "L1StandardBridge_for_verification_only": "0x86E10B59cFDFeFBCf3ED5b40D018949CbFCE8B59", + "TssDelegationManager": "0x36fCf02Fc651c0b7ef2ECA446Dd2405364F85337", + "ChugSplashDictator": "0x1Edd37fc504513bAa00D782E52478d0a3f675553", + "Proxy__BVM_EigenDataLayrChain": "0x8013ac56e4c4A562b72a6D8B39D60cDa7aE173A9", "Proxy__BVM_L1CrossDomainMessenger": "0xd9e2F450525079e1e29fB23Bc7Caca6F61f8fD4a", - "Proxy__TSS_StakingSlashing": "0xe6cd9e7b620964bECd42c7Ad41e56724f515E284", + "Proxy__TSS_StakingSlashing": "0x9c28c8D298ae7Ebf8daA6FA54e1F2909313dB158", "BondManager": "0xEd5166f12FCb48a0804B62FDccB37f59F1F1bc3B", - "AssertionMap": "0x1Edd37fc504513bAa00D782E52478d0a3f675553", - "Proxy__Rollup": "0x8013ac56e4c4A562b72a6D8B39D60cDa7aE173A9", + "AssertionMap": "0xb416faEaEf670632Db2Ad66558e74aaD6518FB84", + "Proxy__Rollup": "0x90c9E4f7F11C93BCec2e1F272b2063640d3bb264", "AddressManager": "0x19C22f181280dF6Ad1d97285cdD430173Df91C12" } diff --git a/packages/contracts/genesis/local.json b/packages/contracts/genesis/local.json index aed21eca5..f89659846 100644 --- a/packages/contracts/genesis/local.json +++ b/packages/contracts/genesis/local.json @@ -1,5 +1,5 @@ { - "commit": "7173bdc0171da8ba2128f6553cf00846fc0e51ee", + "commit": "3a907851d804b00685484bb88501f9e383c4769a", "config": { "chainId": 17, "homesteadBlock": 0, @@ -127,7 +127,7 @@ "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000004200000000000000000000000000000000000007", "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0000000000000000000000008baccff561fde61d6bc8b6f299ffba561d2189b9" }, - "code": "0x6080604052600436106101235760003560e01c80633cb747bf116100a0578063d8111a5711610064578063d8111a571461030c578063e5efd58514610322578063ea01cd3614610338578063f2fde38b14610358578063fad9aba31461037857600080fd5b80633cb747bf1461028f5780633ccfd60b146102af578063715018a6146102c45780638da5cb5b146102d9578063cfb550f1146102f757600080fd5b806319d509a1116100e757806319d509a11461020e5780631a39d8ef1461022457806327c8f8351461023a5780632c79db111461025a5780633b52c31e1461026f57600080fd5b80630b50cd3e1461012f5780630fae75d91461016457806310a7fd7b14610186578063110b7eb0146101c157806315c6f166146101f957600080fd5b3661012a57005b600080fd5b34801561013b57600080fd5b5061014f61014a366004610d5c565b61038e565b60405190151581526020015b60405180910390f35b34801561017057600080fd5b5061018461017f366004610d7e565b6104a9565b005b34801561019257600080fd5b506101b36101a1366004610e20565b60026020526000908152604090205481565b60405190815260200161015b565b3480156101cd57600080fd5b506003546101e1906001600160a01b031681565b6040516001600160a01b03909116815260200161015b565b34801561020557600080fd5b506101b36108a6565b34801561021a57600080fd5b506101b360065481565b34801561023057600080fd5b506101b360075481565b34801561024657600080fd5b506004546101e1906001600160a01b031681565b34801561026657600080fd5b506101b36108d1565b34801561027b57600080fd5b5061018461028a366004610e20565b6108fa565b34801561029b57600080fd5b506001546101e1906001600160a01b031681565b3480156102bb57600080fd5b50610184610929565b3480156102d057600080fd5b506101846109be565b3480156102e557600080fd5b506000546001600160a01b03166101e1565b34801561030357600080fd5b506101846109f2565b34801561031857600080fd5b506101b360095481565b34801561032e57600080fd5b506101b360085481565b34801561034457600080fd5b50600a546101e1906001600160a01b031681565b34801561036457600080fd5b50610184610373366004610e4e565b610a9b565b34801561038457600080fd5b506101b360055481565b6004546000906001600160a01b031633146104005760405162461bcd60e51b815260206004820152602760248201527f747373207265776172642063616c6c206d65737361676520756e61757468656e6044820152661d1a58d85d195960ca1b60648201526084015b60405180910390fd5b6007544710156104225760405162461bcd60e51b81526004016103f790610e6b565b600654610430906001610ed2565b831461047e5760405162461bcd60e51b815260206004820152601760248201527f626c6f636b2069642075706461746520696c6c6567616c00000000000000000060448201526064016103f7565b60068390556007546104909083610b33565b6007555060009182526002602052604090912055600190565b600a546001600160a01b03166104c76001546001600160a01b031690565b6001600160a01b0316336001600160a01b03161461053e5760405162461bcd60e51b815260206004820152602e60248201527f42564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201526d1b985d5d1a195b9d1a58d85d195960921b60648201526084016103f7565b806001600160a01b031661055a6001546001600160a01b031690565b6001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b15801561059257600080fd5b505afa1580156105a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ca9190610eea565b6001600160a01b0316146106395760405162461bcd60e51b815260206004820152603060248201527f42564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201526f732d646f6d61696e206d65737361676560801b60648201526084016103f7565b600360009054906101000a90046001600160a01b03166001600160a01b0316630d1e43a06040518163ffffffff1660e01b815260040160206040518083038186803b15801561068757600080fd5b505afa15801561069b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bf9190610f07565b6001146106d7576106d286868585610b46565b61089e565b6000806000600854600014156106f457505050600884905561089e565b60085487116107605760405162461bcd60e51b815260206004820152603260248201527f61726773205f626174636854696d65206d757374206774686572207468616e206044820152716c617374206c617374426174636854696d6560701b60648201526084016103f7565b60055461076b6108a6565b600854610778908a610f20565b6107829190610f37565b61078c9190610ed2565b6000600555915061079d8286610cf4565b925060005b8581101561082d5760008787838181106107be576107be610f56565b90506020020160208101906107d39190610e4e565b90506107df8386610b33565b6040519093506001600160a01b0382169086156108fc029087906000818181858888f19350505050158015610818573d6000803e3d6000fd5b5050808061082590610f6c565b9150506107a2565b50600061083a8383610d00565b905080156108535760055461084f9082610b33565b6005555b7ff533ef50019763ee9d95ad46e28350b533c11edd472ae7be93e8fae83c1b6d9960085489868a8a60405161088c959493929190610fd0565b60405180910390a15050506008859055505b505050505050565b60006108cc6301e13380600954670de0b6b3a76400006108c69190610f37565b90610cf4565b905090565b60006007544710156108f55760405162461bcd60e51b81526004016103f790610e6b565b504790565b6000546001600160a01b031633146109245760405162461bcd60e51b81526004016103f790611001565b600955565b6000546001600160a01b031633146109535760405162461bcd60e51b81526004016103f790611001565b6007544710156109755760405162461bcd60e51b81526004016103f790610e6b565b600060075547156109bc57600080546040516001600160a01b03909116914780156108fc02929091818181858888f193505050501580156109ba573d6000803e3d6000fd5b505b565b6000546001600160a01b031633146109e85760405162461bcd60e51b81526004016103f790611001565b6109bc6000610d0c565b6000546001600160a01b03163314610a1c5760405162461bcd60e51b81526004016103f790611001565b600754471015610a3e5760405162461bcd60e51b81526004016103f790610e6b565b600554600754610a4e9082610d00565b600755600060055580156109ba57600080546005546040516001600160a01b039092169281156108fc029290818181858888f19350505050158015610a97573d6000803e3d6000fd5b5050565b6000546001600160a01b03163314610ac55760405162461bcd60e51b81526004016103f790611001565b6001600160a01b038116610b2a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016103f7565b6109ba81610d0c565b6000610b3f8284610ed2565b9392505050565b6000806000805b8663ffffffff16811015610bbf57610b8a60026000610b6c848c610ed2565b81526020019081526020016000205484610b3390919063ffffffff16565b925060026000610b9a838b610ed2565b8152602001908152602001600020600090558080610bb790610f6c565b915050610b4d565b508115610cac57600554610bd39083610ed2565b60006005559150610be48285610cf4565b925060005b84811015610c84576000868683818110610c0557610c05610f56565b9050602002016020810190610c1a9190610e4e565b9050610c268386610b33565b600754909350610c369086610d00565b6007556040516001600160a01b0382169086156108fc029087906000818181858888f19350505050158015610c6f573d6000803e3d6000fd5b50508080610c7c90610f6c565b915050610be9565b506000610c918383610d00565b90508015610caa57600554610ca69082610b33565b6005555b505b7f2dae6f3d42a2c50d6baa3ea3f2423a9e1ff0ba26875f8ba6ba25c40df98009fe8787858888604051610ce3959493929190611036565b60405180910390a150505050505050565b6000610b3f8284611062565b6000610b3f8284610f20565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008060408385031215610d6f57600080fd5b50508035926020909101359150565b600080600080600060808688031215610d9657600080fd5b85359450602086013563ffffffff81168114610db157600080fd5b935060408601359250606086013567ffffffffffffffff80821115610dd557600080fd5b818801915088601f830112610de957600080fd5b813581811115610df857600080fd5b8960208260051b8501011115610e0d57600080fd5b9699959850939650602001949392505050565b600060208284031215610e3257600080fd5b5035919050565b6001600160a01b03811681146109ba57600080fd5b600060208284031215610e6057600080fd5b8135610b3f81610e39565b60208082526031908201527f62616c616e6365207265636f726420616e6420636f6e74726163742062616c616040820152701b98d948185c99481b9bdd08195c5d585b607a1b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b60008219821115610ee557610ee5610ebc565b500190565b600060208284031215610efc57600080fd5b8151610b3f81610e39565b600060208284031215610f1957600080fd5b5051919050565b600082821015610f3257610f32610ebc565b500390565b6000816000190483118215151615610f5157610f51610ebc565b500290565b634e487b7160e01b600052603260045260246000fd5b6000600019821415610f8057610f80610ebc565b5060010190565b8183526000602080850194508260005b85811015610fc5578135610faa81610e39565b6001600160a01b031687529582019590820190600101610f97565b509495945050505050565b858152846020820152836040820152608060608201526000610ff6608083018486610f87565b979650505050505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b85815263ffffffff85166020820152836040820152608060608201526000610ff6608083018486610f87565b60008261107f57634e487b7160e01b600052601260045260246000fd5b50049056fea2646970667358221220796ffabdfbad4bc4abcc71948bad22b7a53f5250cc041d698f8f6ba035dd424f64736f6c63430008090033" + "code": "0x6080604052600436106101f25760003560e01c80638da5cb5b1161010d578063d8111a57116100a0578063ebc73e651161006f578063ebc73e6514610585578063f2fde38b146105a5578063f5cf673b146105c5578063f7c618c1146105e5578063fad9aba31461060557600080fd5b8063d8111a5714610503578063da62fba914610519578063e5efd5851461054f578063ea01cd361461056557600080fd5b8063ceddc021116100dc578063ceddc02114610497578063cf172403146104ac578063cfb550f1146104d9578063d4440a36146104ee57600080fd5b80638da5cb5b14610420578063904ad6be1461043e578063aa13e8c214610454578063b89ea4021461046a57600080fd5b806327c8f835116101855780633ccfd60b116101545780633ccfd60b146103b45780634e71d92d146103c957806352674ea5146103de578063715018a61461040b57600080fd5b806327c8f8351461033f5780632c79db111461035f5780633b52c31e146103745780633cb747bf1461039457600080fd5b806313e7c9d8116101c157806313e7c9d8146102c857806315c6f166146102fe57806319d509a1146103135780631a39d8ef1461032957600080fd5b80630b50cd3e146101fe5780630fae75d91461023357806310a7fd7b14610255578063110b7eb01461029057600080fd5b366101f957005b600080fd5b34801561020a57600080fd5b5061021e6102193660046116d7565b61061b565b60405190151581526020015b60405180910390f35b34801561023f57600080fd5b5061025361024e3660046116f9565b610736565b005b34801561026157600080fd5b5061028261027036600461179b565b60026020526000908152604090205481565b60405190815260200161022a565b34801561029c57600080fd5b506003546102b0906001600160a01b031681565b6040516001600160a01b03909116815260200161022a565b3480156102d457600080fd5b506102b06102e33660046117c9565b600e602052600090815260409020546001600160a01b031681565b34801561030a57600080fd5b506102826109eb565b34801561031f57600080fd5b5061028260065481565b34801561033557600080fd5b5061028260075481565b34801561034b57600080fd5b506004546102b0906001600160a01b031681565b34801561036b57600080fd5b50610282610a16565b34801561038057600080fd5b5061025361038f36600461179b565b610a3f565b3480156103a057600080fd5b506001546102b0906001600160a01b031681565b3480156103c057600080fd5b50610253610a6e565b3480156103d557600080fd5b50610253610b6f565b3480156103ea57600080fd5b506102826103f93660046117c9565b60116020526000908152604090205481565b34801561041757600080fd5b50610253610c50565b34801561042c57600080fd5b506000546001600160a01b03166102b0565b34801561044a57600080fd5b50610282600b5481565b34801561046057600080fd5b50610282600c5481565b34801561047657600080fd5b506102826104853660046117c9565b60106020526000908152604090205481565b3480156104a357600080fd5b5061021e610c86565b3480156104b857600080fd5b506102826104c73660046117c9565b600d6020526000908152604090205481565b3480156104e557600080fd5b50610253610db5565b3480156104fa57600080fd5b50610282610e34565b34801561050f57600080fd5b5061028260095481565b34801561052557600080fd5b506102b06105343660046117c9565b600f602052600090815260409020546001600160a01b031681565b34801561055b57600080fd5b5061028260085481565b34801561057157600080fd5b50600a546102b0906001600160a01b031681565b34801561059157600080fd5b506102536105a036600461179b565b610e95565b3480156105b157600080fd5b506102536105c03660046117c9565b610ec4565b3480156105d157600080fd5b506102536105e03660046117e6565b610f5c565b3480156105f157600080fd5b506012546102b0906001600160a01b031681565b34801561061157600080fd5b5061028260055481565b6004546000906001600160a01b0316331461068d5760405162461bcd60e51b815260206004820152602760248201527f747373207265776172642063616c6c206d65737361676520756e61757468656e6044820152661d1a58d85d195960ca1b60648201526084015b60405180910390fd5b6007544710156106af5760405162461bcd60e51b81526004016106849061181f565b6006546106bd906001611886565b831461070b5760405162461bcd60e51b815260206004820152601760248201527f626c6f636b2069642075706461746520696c6c6567616c0000000000000000006044820152606401610684565b600683905560075461071d90836110a7565b6007555060009182526002602052604090912055600190565b600a546001600160a01b03166107546001546001600160a01b031690565b6001600160a01b0316336001600160a01b0316146107845760405162461bcd60e51b81526004016106849061189e565b806001600160a01b03166107a06001546001600160a01b031690565b6001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b1580156107d857600080fd5b505afa1580156107ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061081091906118ec565b6001600160a01b0316146108365760405162461bcd60e51b815260040161068490611909565b600360009054906101000a90046001600160a01b03166001600160a01b0316630d1e43a06040518163ffffffff1660e01b815260040160206040518083038186803b15801561088457600080fd5b505afa158015610898573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108bc9190611959565b6001146108d4576108cf868685856110ba565b6109e3565b6000600854600014156108ec575060088490556109e3565b60085485116109585760405162461bcd60e51b815260206004820152603260248201527f61726773205f626174636854696d65206d757374206774686572207468616e206044820152716c617374206c617374426174636854696d6560701b6064820152608401610684565b6005546109636109eb565b6008546109709088611972565b61097a9190611989565b6109849190611886565b9050600060058190555061099b81858560006111a3565b7ff533ef50019763ee9d95ad46e28350b533c11edd472ae7be93e8fae83c1b6d99600854868387876040516109d49594939291906119f1565b60405180910390a15060088490555b505050505050565b6000610a116301e13380600954670de0b6b3a7640000610a0b9190611989565b906112a0565b905090565b6000600754471015610a3a5760405162461bcd60e51b81526004016106849061181f565b504790565b6000546001600160a01b03163314610a695760405162461bcd60e51b815260040161068490611a17565b600955565b6000546001600160a01b03163314610a985760405162461bcd60e51b815260040161068490611a17565b600754471015610aba5760405162461bcd60e51b81526004016106849061181f565b600060078190556012546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b158015610b0457600080fd5b505afa158015610b18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3c9190611959565b90508015610b6c57610b6c610b596000546001600160a01b031690565b6012546001600160a01b031690836112ac565b50565b336000908152600f60205260409020546001600160a01b031680610ba55760405162461bcd60e51b815260040161068490611a4c565b336000908152600f60205260408120546001600160a01b031690610bc882611303565b90508015610c2b5760405162461bcd60e51b815260206004820152602a60248201527f706c65617365207761697420666f72207468652077616974696e6720706572696044820152696f6420746f207061737360b01b6064820152608401610684565b610c34826113b3565b506001600160a01b031660009081526010602052604081205550565b6000546001600160a01b03163314610c7a5760405162461bcd60e51b815260040161068490611a17565b610c84600061149e565b565b336000908152600f60205260408120546001600160a01b031680610cbc5760405162461bcd60e51b815260040161068490611a4c565b336000908152600f60209081526040808320546001600160a01b03168084526010909252909120548015610d7e5760405162461bcd60e51b815260206004820152605960248201527f596f75206861766520616c726561647920696e6974696174656420612072657160448201527f7565737420746f20636c61696d2c20706c65617365207761697420666f72207460648201527f68652077616974696e6720706572696f6420746f207061737300000000000000608482015260a401610684565b506001600160a01b03166000908152601060209081526040808320429055600d825280832054601190925290912055600191505090565b6000546001600160a01b03163314610ddf5760405162461bcd60e51b815260040161068490611a17565b600754471015610e015760405162461bcd60e51b81526004016106849061181f565b600b54600754610e1190826114ee565b6007556000600b558015610b6c57610b6c610b596000546001600160a01b031690565b336000908152600f60205260408120546001600160a01b031680610e6a5760405162461bcd60e51b815260040161068490611a4c565b336000908152600f60205260408120546001600160a01b031690610e8d82611303565b935050505090565b6000546001600160a01b03163314610ebf5760405162461bcd60e51b815260040161068490611a17565b600c55565b6000546001600160a01b03163314610eee5760405162461bcd60e51b815260040161068490611a17565b6001600160a01b038116610f535760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610684565b610b6c8161149e565b600a546001600160a01b0316610f7a6001546001600160a01b031690565b6001600160a01b0316336001600160a01b031614610faa5760405162461bcd60e51b81526004016106849061189e565b806001600160a01b0316610fc66001546001600160a01b031690565b6001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b158015610ffe57600080fd5b505afa158015611012573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103691906118ec565b6001600160a01b03161461105c5760405162461bcd60e51b815260040161068490611909565b506001600160a01b039081166000818152600f602090815260408083208054959096166001600160a01b03199586168117909655948252600e90529290922080549091169091179055565b60006110b38284611886565b9392505050565b6000806000805b8663ffffffff16811015611133576110fe600260006110e0848c611886565b815260200190815260200160002054846110a790919063ffffffff16565b92506002600061110e838b611886565b815260200190815260200160002060009055808061112b90611a9d565b9150506110c1565b50811561115b57600b546111479083611886565b6000600b55915061115b82868660016111a3565b7f2dae6f3d42a2c50d6baa3ea3f2423a9e1ff0ba26875f8ba6ba25c40df98009fe8787858888604051611192959493929190611ab8565b60405180910390a150505050505050565b831561129a576000806111b686856112a0565b915060005b848110156112555760008686838181106111d7576111d7611ae4565b90506020020160208101906111ec91906117c9565b6001600160a01b0381166000908152600d6020526040812080549293508692909190611219908490611886565b90915550611229905083856110a7565b925084156112425760075461123e90856114ee565b6007555b508061124d81611a9d565b9150506111bb565b50600061126287836114ee565b9050801561129657831561128557600b5461127d90826110a7565b600b55611296565b60055461129290826110a7565b6005555b5050505b50505050565b60006110b38284611afa565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526112fe9084906114fa565b505050565b6001600160a01b0381166000908152601060205260408120548061137a5760405162461bcd60e51b815260206004820152602860248201527f706c6561736520696e6974696174652061207265717565737420746f20636c616044820152671a5b48199a5c9cdd60c21b6064820152608401610684565b6000600c548261138a9190611886565b90506000428211156113a7576113a04283611972565b90506113ab565b5060005b949350505050565b6001600160a01b038116600090815260116020908152604080832054600d909252909120548115611457576001600160a01b038084166000908152600e60205260409020546012549082169161140b911682856112ac565b6001600160a01b0384166000908152601160209081526040808320839055600d90915290205461143c908490611972565b6001600160a01b0385166000908152600d6020526040902055505b604080516001600160a01b0385168152602081018390527f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4910160405180910390a1505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006110b38284611972565b600061154f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166115cc9092919063ffffffff16565b8051909150156112fe578080602001905181019061156d9190611b1c565b6112fe5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610684565b60606113ab848460008585843b6116255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610684565b600080866001600160a01b031685876040516116419190611b6a565b60006040518083038185875af1925050503d806000811461167e576040519150601f19603f3d011682016040523d82523d6000602084013e611683565b606091505b509150915061169382828661169e565b979650505050505050565b606083156116ad5750816110b3565b8251156116bd5782518084602001fd5b8160405162461bcd60e51b81526004016106849190611b86565b600080604083850312156116ea57600080fd5b50508035926020909101359150565b60008060008060006080868803121561171157600080fd5b85359450602086013563ffffffff8116811461172c57600080fd5b935060408601359250606086013567ffffffffffffffff8082111561175057600080fd5b818801915088601f83011261176457600080fd5b81358181111561177357600080fd5b8960208260051b850101111561178857600080fd5b9699959850939650602001949392505050565b6000602082840312156117ad57600080fd5b5035919050565b6001600160a01b0381168114610b6c57600080fd5b6000602082840312156117db57600080fd5b81356110b3816117b4565b600080604083850312156117f957600080fd5b8235611804816117b4565b91506020830135611814816117b4565b809150509250929050565b60208082526031908201527f62616c616e6365207265636f726420616e6420636f6e74726163742062616c616040820152701b98d948185c99481b9bdd08195c5d585b607a1b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b6000821982111561189957611899611870565b500190565b6020808252602e908201527f42564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560408201526d1b985d5d1a195b9d1a58d85d195960921b606082015260800190565b6000602082840312156118fe57600080fd5b81516110b3816117b4565b60208082526030908201527f42564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360408201526f732d646f6d61696e206d65737361676560801b606082015260800190565b60006020828403121561196b57600080fd5b5051919050565b60008282101561198457611984611870565b500390565b60008160001904831182151516156119a3576119a3611870565b500290565b8183526000602080850194508260005b858110156119e65781356119cb816117b4565b6001600160a01b0316875295820195908201906001016119b8565b509495945050505050565b8581528460208201528360408201526080606082015260006116936080830184866119a8565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f546865206d73672073656e646572206973206e6f7420617574686f72697a656460408201527010313c903a3432903b30b634b230ba37b960791b606082015260800190565b6000600019821415611ab157611ab1611870565b5060010190565b85815263ffffffff851660208201528360408201526080606082015260006116936080830184866119a8565b634e487b7160e01b600052603260045260246000fd5b600082611b1757634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215611b2e57600080fd5b815180151581146110b357600080fd5b60005b83811015611b59578181015183820152602001611b41565b8381111561129a5750506000910152565b60008251611b7c818460208701611b3e565b9190910192915050565b6020815260008251806020840152611ba5816040850160208701611b3e565b601f01601f1916919091016040019291505056fea264697066735822122069e8dc69d2dea3aa8eb57c54a7e00df44e871a792812d5eb6d7e6659cf91a3a164736f6c63430008090033" } } -} \ No newline at end of file +} diff --git a/packages/contracts/genesis/state-dump.latest.json b/packages/contracts/genesis/state-dump.latest.json index 8118bef97..a72f2c8f1 100644 --- a/packages/contracts/genesis/state-dump.latest.json +++ b/packages/contracts/genesis/state-dump.latest.json @@ -1,5 +1,5 @@ { - "commit": "7173bdc0171da8ba2128f6553cf00846fc0e51ee", + "commit": "3a907851d804b00685484bb88501f9e383c4769a", "config": { "chainId": 17, "homesteadBlock": 0, @@ -127,7 +127,7 @@ "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000004200000000000000000000000000000000000007", "0x000000000000000000000000000000000000000000000000000000000000000a": "0x0000000000000000000000008baccff561fde61d6bc8b6f299ffba561d2189b9" }, - "code": "0x6080604052600436106101235760003560e01c80633cb747bf116100a0578063d8111a5711610064578063d8111a571461030c578063e5efd58514610322578063ea01cd3614610338578063f2fde38b14610358578063fad9aba31461037857600080fd5b80633cb747bf1461028f5780633ccfd60b146102af578063715018a6146102c45780638da5cb5b146102d9578063cfb550f1146102f757600080fd5b806319d509a1116100e757806319d509a11461020e5780631a39d8ef1461022457806327c8f8351461023a5780632c79db111461025a5780633b52c31e1461026f57600080fd5b80630b50cd3e1461012f5780630fae75d91461016457806310a7fd7b14610186578063110b7eb0146101c157806315c6f166146101f957600080fd5b3661012a57005b600080fd5b34801561013b57600080fd5b5061014f61014a366004610d5c565b61038e565b60405190151581526020015b60405180910390f35b34801561017057600080fd5b5061018461017f366004610d7e565b6104a9565b005b34801561019257600080fd5b506101b36101a1366004610e20565b60026020526000908152604090205481565b60405190815260200161015b565b3480156101cd57600080fd5b506003546101e1906001600160a01b031681565b6040516001600160a01b03909116815260200161015b565b34801561020557600080fd5b506101b36108a6565b34801561021a57600080fd5b506101b360065481565b34801561023057600080fd5b506101b360075481565b34801561024657600080fd5b506004546101e1906001600160a01b031681565b34801561026657600080fd5b506101b36108d1565b34801561027b57600080fd5b5061018461028a366004610e20565b6108fa565b34801561029b57600080fd5b506001546101e1906001600160a01b031681565b3480156102bb57600080fd5b50610184610929565b3480156102d057600080fd5b506101846109be565b3480156102e557600080fd5b506000546001600160a01b03166101e1565b34801561030357600080fd5b506101846109f2565b34801561031857600080fd5b506101b360095481565b34801561032e57600080fd5b506101b360085481565b34801561034457600080fd5b50600a546101e1906001600160a01b031681565b34801561036457600080fd5b50610184610373366004610e4e565b610a9b565b34801561038457600080fd5b506101b360055481565b6004546000906001600160a01b031633146104005760405162461bcd60e51b815260206004820152602760248201527f747373207265776172642063616c6c206d65737361676520756e61757468656e6044820152661d1a58d85d195960ca1b60648201526084015b60405180910390fd5b6007544710156104225760405162461bcd60e51b81526004016103f790610e6b565b600654610430906001610ed2565b831461047e5760405162461bcd60e51b815260206004820152601760248201527f626c6f636b2069642075706461746520696c6c6567616c00000000000000000060448201526064016103f7565b60068390556007546104909083610b33565b6007555060009182526002602052604090912055600190565b600a546001600160a01b03166104c76001546001600160a01b031690565b6001600160a01b0316336001600160a01b03161461053e5760405162461bcd60e51b815260206004820152602e60248201527f42564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560448201526d1b985d5d1a195b9d1a58d85d195960921b60648201526084016103f7565b806001600160a01b031661055a6001546001600160a01b031690565b6001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b15801561059257600080fd5b505afa1580156105a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ca9190610eea565b6001600160a01b0316146106395760405162461bcd60e51b815260206004820152603060248201527f42564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360448201526f732d646f6d61696e206d65737361676560801b60648201526084016103f7565b600360009054906101000a90046001600160a01b03166001600160a01b0316630d1e43a06040518163ffffffff1660e01b815260040160206040518083038186803b15801561068757600080fd5b505afa15801561069b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bf9190610f07565b6001146106d7576106d286868585610b46565b61089e565b6000806000600854600014156106f457505050600884905561089e565b60085487116107605760405162461bcd60e51b815260206004820152603260248201527f61726773205f626174636854696d65206d757374206774686572207468616e206044820152716c617374206c617374426174636854696d6560701b60648201526084016103f7565b60055461076b6108a6565b600854610778908a610f20565b6107829190610f37565b61078c9190610ed2565b6000600555915061079d8286610cf4565b925060005b8581101561082d5760008787838181106107be576107be610f56565b90506020020160208101906107d39190610e4e565b90506107df8386610b33565b6040519093506001600160a01b0382169086156108fc029087906000818181858888f19350505050158015610818573d6000803e3d6000fd5b5050808061082590610f6c565b9150506107a2565b50600061083a8383610d00565b905080156108535760055461084f9082610b33565b6005555b7ff533ef50019763ee9d95ad46e28350b533c11edd472ae7be93e8fae83c1b6d9960085489868a8a60405161088c959493929190610fd0565b60405180910390a15050506008859055505b505050505050565b60006108cc6301e13380600954670de0b6b3a76400006108c69190610f37565b90610cf4565b905090565b60006007544710156108f55760405162461bcd60e51b81526004016103f790610e6b565b504790565b6000546001600160a01b031633146109245760405162461bcd60e51b81526004016103f790611001565b600955565b6000546001600160a01b031633146109535760405162461bcd60e51b81526004016103f790611001565b6007544710156109755760405162461bcd60e51b81526004016103f790610e6b565b600060075547156109bc57600080546040516001600160a01b03909116914780156108fc02929091818181858888f193505050501580156109ba573d6000803e3d6000fd5b505b565b6000546001600160a01b031633146109e85760405162461bcd60e51b81526004016103f790611001565b6109bc6000610d0c565b6000546001600160a01b03163314610a1c5760405162461bcd60e51b81526004016103f790611001565b600754471015610a3e5760405162461bcd60e51b81526004016103f790610e6b565b600554600754610a4e9082610d00565b600755600060055580156109ba57600080546005546040516001600160a01b039092169281156108fc029290818181858888f19350505050158015610a97573d6000803e3d6000fd5b5050565b6000546001600160a01b03163314610ac55760405162461bcd60e51b81526004016103f790611001565b6001600160a01b038116610b2a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016103f7565b6109ba81610d0c565b6000610b3f8284610ed2565b9392505050565b6000806000805b8663ffffffff16811015610bbf57610b8a60026000610b6c848c610ed2565b81526020019081526020016000205484610b3390919063ffffffff16565b925060026000610b9a838b610ed2565b8152602001908152602001600020600090558080610bb790610f6c565b915050610b4d565b508115610cac57600554610bd39083610ed2565b60006005559150610be48285610cf4565b925060005b84811015610c84576000868683818110610c0557610c05610f56565b9050602002016020810190610c1a9190610e4e565b9050610c268386610b33565b600754909350610c369086610d00565b6007556040516001600160a01b0382169086156108fc029087906000818181858888f19350505050158015610c6f573d6000803e3d6000fd5b50508080610c7c90610f6c565b915050610be9565b506000610c918383610d00565b90508015610caa57600554610ca69082610b33565b6005555b505b7f2dae6f3d42a2c50d6baa3ea3f2423a9e1ff0ba26875f8ba6ba25c40df98009fe8787858888604051610ce3959493929190611036565b60405180910390a150505050505050565b6000610b3f8284611062565b6000610b3f8284610f20565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008060408385031215610d6f57600080fd5b50508035926020909101359150565b600080600080600060808688031215610d9657600080fd5b85359450602086013563ffffffff81168114610db157600080fd5b935060408601359250606086013567ffffffffffffffff80821115610dd557600080fd5b818801915088601f830112610de957600080fd5b813581811115610df857600080fd5b8960208260051b8501011115610e0d57600080fd5b9699959850939650602001949392505050565b600060208284031215610e3257600080fd5b5035919050565b6001600160a01b03811681146109ba57600080fd5b600060208284031215610e6057600080fd5b8135610b3f81610e39565b60208082526031908201527f62616c616e6365207265636f726420616e6420636f6e74726163742062616c616040820152701b98d948185c99481b9bdd08195c5d585b607a1b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b60008219821115610ee557610ee5610ebc565b500190565b600060208284031215610efc57600080fd5b8151610b3f81610e39565b600060208284031215610f1957600080fd5b5051919050565b600082821015610f3257610f32610ebc565b500390565b6000816000190483118215151615610f5157610f51610ebc565b500290565b634e487b7160e01b600052603260045260246000fd5b6000600019821415610f8057610f80610ebc565b5060010190565b8183526000602080850194508260005b85811015610fc5578135610faa81610e39565b6001600160a01b031687529582019590820190600101610f97565b509495945050505050565b858152846020820152836040820152608060608201526000610ff6608083018486610f87565b979650505050505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b85815263ffffffff85166020820152836040820152608060608201526000610ff6608083018486610f87565b60008261107f57634e487b7160e01b600052601260045260246000fd5b50049056fea2646970667358221220796ffabdfbad4bc4abcc71948bad22b7a53f5250cc041d698f8f6ba035dd424f64736f6c63430008090033" + "code": "0x6080604052600436106101f25760003560e01c80638da5cb5b1161010d578063d8111a57116100a0578063ebc73e651161006f578063ebc73e6514610585578063f2fde38b146105a5578063f5cf673b146105c5578063f7c618c1146105e5578063fad9aba31461060557600080fd5b8063d8111a5714610503578063da62fba914610519578063e5efd5851461054f578063ea01cd361461056557600080fd5b8063ceddc021116100dc578063ceddc02114610497578063cf172403146104ac578063cfb550f1146104d9578063d4440a36146104ee57600080fd5b80638da5cb5b14610420578063904ad6be1461043e578063aa13e8c214610454578063b89ea4021461046a57600080fd5b806327c8f835116101855780633ccfd60b116101545780633ccfd60b146103b45780634e71d92d146103c957806352674ea5146103de578063715018a61461040b57600080fd5b806327c8f8351461033f5780632c79db111461035f5780633b52c31e146103745780633cb747bf1461039457600080fd5b806313e7c9d8116101c157806313e7c9d8146102c857806315c6f166146102fe57806319d509a1146103135780631a39d8ef1461032957600080fd5b80630b50cd3e146101fe5780630fae75d91461023357806310a7fd7b14610255578063110b7eb01461029057600080fd5b366101f957005b600080fd5b34801561020a57600080fd5b5061021e6102193660046116d7565b61061b565b60405190151581526020015b60405180910390f35b34801561023f57600080fd5b5061025361024e3660046116f9565b610736565b005b34801561026157600080fd5b5061028261027036600461179b565b60026020526000908152604090205481565b60405190815260200161022a565b34801561029c57600080fd5b506003546102b0906001600160a01b031681565b6040516001600160a01b03909116815260200161022a565b3480156102d457600080fd5b506102b06102e33660046117c9565b600e602052600090815260409020546001600160a01b031681565b34801561030a57600080fd5b506102826109eb565b34801561031f57600080fd5b5061028260065481565b34801561033557600080fd5b5061028260075481565b34801561034b57600080fd5b506004546102b0906001600160a01b031681565b34801561036b57600080fd5b50610282610a16565b34801561038057600080fd5b5061025361038f36600461179b565b610a3f565b3480156103a057600080fd5b506001546102b0906001600160a01b031681565b3480156103c057600080fd5b50610253610a6e565b3480156103d557600080fd5b50610253610b6f565b3480156103ea57600080fd5b506102826103f93660046117c9565b60116020526000908152604090205481565b34801561041757600080fd5b50610253610c50565b34801561042c57600080fd5b506000546001600160a01b03166102b0565b34801561044a57600080fd5b50610282600b5481565b34801561046057600080fd5b50610282600c5481565b34801561047657600080fd5b506102826104853660046117c9565b60106020526000908152604090205481565b3480156104a357600080fd5b5061021e610c86565b3480156104b857600080fd5b506102826104c73660046117c9565b600d6020526000908152604090205481565b3480156104e557600080fd5b50610253610db5565b3480156104fa57600080fd5b50610282610e34565b34801561050f57600080fd5b5061028260095481565b34801561052557600080fd5b506102b06105343660046117c9565b600f602052600090815260409020546001600160a01b031681565b34801561055b57600080fd5b5061028260085481565b34801561057157600080fd5b50600a546102b0906001600160a01b031681565b34801561059157600080fd5b506102536105a036600461179b565b610e95565b3480156105b157600080fd5b506102536105c03660046117c9565b610ec4565b3480156105d157600080fd5b506102536105e03660046117e6565b610f5c565b3480156105f157600080fd5b506012546102b0906001600160a01b031681565b34801561061157600080fd5b5061028260055481565b6004546000906001600160a01b0316331461068d5760405162461bcd60e51b815260206004820152602760248201527f747373207265776172642063616c6c206d65737361676520756e61757468656e6044820152661d1a58d85d195960ca1b60648201526084015b60405180910390fd5b6007544710156106af5760405162461bcd60e51b81526004016106849061181f565b6006546106bd906001611886565b831461070b5760405162461bcd60e51b815260206004820152601760248201527f626c6f636b2069642075706461746520696c6c6567616c0000000000000000006044820152606401610684565b600683905560075461071d90836110a7565b6007555060009182526002602052604090912055600190565b600a546001600160a01b03166107546001546001600160a01b031690565b6001600160a01b0316336001600160a01b0316146107845760405162461bcd60e51b81526004016106849061189e565b806001600160a01b03166107a06001546001600160a01b031690565b6001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b1580156107d857600080fd5b505afa1580156107ec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061081091906118ec565b6001600160a01b0316146108365760405162461bcd60e51b815260040161068490611909565b600360009054906101000a90046001600160a01b03166001600160a01b0316630d1e43a06040518163ffffffff1660e01b815260040160206040518083038186803b15801561088457600080fd5b505afa158015610898573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108bc9190611959565b6001146108d4576108cf868685856110ba565b6109e3565b6000600854600014156108ec575060088490556109e3565b60085485116109585760405162461bcd60e51b815260206004820152603260248201527f61726773205f626174636854696d65206d757374206774686572207468616e206044820152716c617374206c617374426174636854696d6560701b6064820152608401610684565b6005546109636109eb565b6008546109709088611972565b61097a9190611989565b6109849190611886565b9050600060058190555061099b81858560006111a3565b7ff533ef50019763ee9d95ad46e28350b533c11edd472ae7be93e8fae83c1b6d99600854868387876040516109d49594939291906119f1565b60405180910390a15060088490555b505050505050565b6000610a116301e13380600954670de0b6b3a7640000610a0b9190611989565b906112a0565b905090565b6000600754471015610a3a5760405162461bcd60e51b81526004016106849061181f565b504790565b6000546001600160a01b03163314610a695760405162461bcd60e51b815260040161068490611a17565b600955565b6000546001600160a01b03163314610a985760405162461bcd60e51b815260040161068490611a17565b600754471015610aba5760405162461bcd60e51b81526004016106849061181f565b600060078190556012546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b158015610b0457600080fd5b505afa158015610b18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3c9190611959565b90508015610b6c57610b6c610b596000546001600160a01b031690565b6012546001600160a01b031690836112ac565b50565b336000908152600f60205260409020546001600160a01b031680610ba55760405162461bcd60e51b815260040161068490611a4c565b336000908152600f60205260408120546001600160a01b031690610bc882611303565b90508015610c2b5760405162461bcd60e51b815260206004820152602a60248201527f706c65617365207761697420666f72207468652077616974696e6720706572696044820152696f6420746f207061737360b01b6064820152608401610684565b610c34826113b3565b506001600160a01b031660009081526010602052604081205550565b6000546001600160a01b03163314610c7a5760405162461bcd60e51b815260040161068490611a17565b610c84600061149e565b565b336000908152600f60205260408120546001600160a01b031680610cbc5760405162461bcd60e51b815260040161068490611a4c565b336000908152600f60209081526040808320546001600160a01b03168084526010909252909120548015610d7e5760405162461bcd60e51b815260206004820152605960248201527f596f75206861766520616c726561647920696e6974696174656420612072657160448201527f7565737420746f20636c61696d2c20706c65617365207761697420666f72207460648201527f68652077616974696e6720706572696f6420746f207061737300000000000000608482015260a401610684565b506001600160a01b03166000908152601060209081526040808320429055600d825280832054601190925290912055600191505090565b6000546001600160a01b03163314610ddf5760405162461bcd60e51b815260040161068490611a17565b600754471015610e015760405162461bcd60e51b81526004016106849061181f565b600b54600754610e1190826114ee565b6007556000600b558015610b6c57610b6c610b596000546001600160a01b031690565b336000908152600f60205260408120546001600160a01b031680610e6a5760405162461bcd60e51b815260040161068490611a4c565b336000908152600f60205260408120546001600160a01b031690610e8d82611303565b935050505090565b6000546001600160a01b03163314610ebf5760405162461bcd60e51b815260040161068490611a17565b600c55565b6000546001600160a01b03163314610eee5760405162461bcd60e51b815260040161068490611a17565b6001600160a01b038116610f535760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610684565b610b6c8161149e565b600a546001600160a01b0316610f7a6001546001600160a01b031690565b6001600160a01b0316336001600160a01b031614610faa5760405162461bcd60e51b81526004016106849061189e565b806001600160a01b0316610fc66001546001600160a01b031690565b6001600160a01b0316636e296e456040518163ffffffff1660e01b815260040160206040518083038186803b158015610ffe57600080fd5b505afa158015611012573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103691906118ec565b6001600160a01b03161461105c5760405162461bcd60e51b815260040161068490611909565b506001600160a01b039081166000818152600f602090815260408083208054959096166001600160a01b03199586168117909655948252600e90529290922080549091169091179055565b60006110b38284611886565b9392505050565b6000806000805b8663ffffffff16811015611133576110fe600260006110e0848c611886565b815260200190815260200160002054846110a790919063ffffffff16565b92506002600061110e838b611886565b815260200190815260200160002060009055808061112b90611a9d565b9150506110c1565b50811561115b57600b546111479083611886565b6000600b55915061115b82868660016111a3565b7f2dae6f3d42a2c50d6baa3ea3f2423a9e1ff0ba26875f8ba6ba25c40df98009fe8787858888604051611192959493929190611ab8565b60405180910390a150505050505050565b831561129a576000806111b686856112a0565b915060005b848110156112555760008686838181106111d7576111d7611ae4565b90506020020160208101906111ec91906117c9565b6001600160a01b0381166000908152600d6020526040812080549293508692909190611219908490611886565b90915550611229905083856110a7565b925084156112425760075461123e90856114ee565b6007555b508061124d81611a9d565b9150506111bb565b50600061126287836114ee565b9050801561129657831561128557600b5461127d90826110a7565b600b55611296565b60055461129290826110a7565b6005555b5050505b50505050565b60006110b38284611afa565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526112fe9084906114fa565b505050565b6001600160a01b0381166000908152601060205260408120548061137a5760405162461bcd60e51b815260206004820152602860248201527f706c6561736520696e6974696174652061207265717565737420746f20636c616044820152671a5b48199a5c9cdd60c21b6064820152608401610684565b6000600c548261138a9190611886565b90506000428211156113a7576113a04283611972565b90506113ab565b5060005b949350505050565b6001600160a01b038116600090815260116020908152604080832054600d909252909120548115611457576001600160a01b038084166000908152600e60205260409020546012549082169161140b911682856112ac565b6001600160a01b0384166000908152601160209081526040808320839055600d90915290205461143c908490611972565b6001600160a01b0385166000908152600d6020526040902055505b604080516001600160a01b0385168152602081018390527f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4910160405180910390a1505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006110b38284611972565b600061154f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166115cc9092919063ffffffff16565b8051909150156112fe578080602001905181019061156d9190611b1c565b6112fe5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610684565b60606113ab848460008585843b6116255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610684565b600080866001600160a01b031685876040516116419190611b6a565b60006040518083038185875af1925050503d806000811461167e576040519150601f19603f3d011682016040523d82523d6000602084013e611683565b606091505b509150915061169382828661169e565b979650505050505050565b606083156116ad5750816110b3565b8251156116bd5782518084602001fd5b8160405162461bcd60e51b81526004016106849190611b86565b600080604083850312156116ea57600080fd5b50508035926020909101359150565b60008060008060006080868803121561171157600080fd5b85359450602086013563ffffffff8116811461172c57600080fd5b935060408601359250606086013567ffffffffffffffff8082111561175057600080fd5b818801915088601f83011261176457600080fd5b81358181111561177357600080fd5b8960208260051b850101111561178857600080fd5b9699959850939650602001949392505050565b6000602082840312156117ad57600080fd5b5035919050565b6001600160a01b0381168114610b6c57600080fd5b6000602082840312156117db57600080fd5b81356110b3816117b4565b600080604083850312156117f957600080fd5b8235611804816117b4565b91506020830135611814816117b4565b809150509250929050565b60208082526031908201527f62616c616e6365207265636f726420616e6420636f6e74726163742062616c616040820152701b98d948185c99481b9bdd08195c5d585b607a1b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b6000821982111561189957611899611870565b500190565b6020808252602e908201527f42564d5f58434841494e3a206d657373656e67657220636f6e7472616374207560408201526d1b985d5d1a195b9d1a58d85d195960921b606082015260800190565b6000602082840312156118fe57600080fd5b81516110b3816117b4565b60208082526030908201527f42564d5f58434841494e3a2077726f6e672073656e646572206f662063726f7360408201526f732d646f6d61696e206d65737361676560801b606082015260800190565b60006020828403121561196b57600080fd5b5051919050565b60008282101561198457611984611870565b500390565b60008160001904831182151516156119a3576119a3611870565b500290565b8183526000602080850194508260005b858110156119e65781356119cb816117b4565b6001600160a01b0316875295820195908201906001016119b8565b509495945050505050565b8581528460208201528360408201526080606082015260006116936080830184866119a8565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526031908201527f546865206d73672073656e646572206973206e6f7420617574686f72697a656460408201527010313c903a3432903b30b634b230ba37b960791b606082015260800190565b6000600019821415611ab157611ab1611870565b5060010190565b85815263ffffffff851660208201528360408201526080606082015260006116936080830184866119a8565b634e487b7160e01b600052603260045260246000fd5b600082611b1757634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215611b2e57600080fd5b815180151581146110b357600080fd5b60005b83811015611b59578181015183820152602001611b41565b8381111561129a5750506000910152565b60008251611b7c818460208701611b3e565b9190910192915050565b6020815260008251806020840152611ba5816040850160208701611b3e565b601f01601f1916919091016040019291505056fea264697066735822122069e8dc69d2dea3aa8eb57c54a7e00df44e871a792812d5eb6d7e6659cf91a3a164736f6c63430008090033" }, "0x63EB358137cd06290544e71210c140B345C6FF10": { "balance": "100000000000000000000000" diff --git a/tss/common/config.go b/tss/common/config.go index 9332326d0..3dda58ac9 100644 --- a/tss/common/config.go +++ b/tss/common/config.go @@ -3,12 +3,13 @@ package common import ( "errors" "fmt" - "github.com/spf13/cobra" - "github.com/spf13/viper" "path" "path/filepath" "strings" "time" + + "github.com/spf13/cobra" + "github.com/spf13/viper" ) type Configuration struct { @@ -26,9 +27,10 @@ type Configuration struct { } type ManagerConfig struct { - WsAddr string `json:"ws_addr" mapstructure:"ws_addr"` - HttpAddr string `json:"http_addr" mapstructure:"http_addr"` - DBDir string `json:"db_dir" mapstructure:"db_dir"` + WsAddr string `json:"ws_addr" mapstructure:"ws_addr"` + HttpAddr string `json:"http_addr" mapstructure:"http_addr"` + DBDir string `json:"db_dir" mapstructure:"db_dir"` + PrivateKey string `json:"private_key" mapstructure:"private_key"` KeygenTimeout string `json:"keygen_timeout" mapstructure:"keygen_timeout"` CPKConfirmTimeout string `json:"cpk_confirm_timeout" mapstructure:"cpk_confirm_timeout"` diff --git a/tss/common/types.go b/tss/common/types.go index ffb5db02a..7c41088d8 100644 --- a/tss/common/types.go +++ b/tss/common/types.go @@ -4,7 +4,6 @@ import ( "encoding/hex" "fmt" "github.com/ethereum/go-ethereum/common" - "math/big" ) type Method string @@ -67,9 +66,6 @@ type NodeSignRequest struct { type SignResponse struct { Signature []byte `json:"signature"` - SlashTxBytes []byte `json:"slash_tx_bytes"` - SlashTxGasPrice string `json:"slash_tx_gas_price"` - SlashTxGasPriceBigInt *big.Int `json:"slash_tx_gas_price_big_int"` } type KeygenRequest struct { diff --git a/tss/common/utils.go b/tss/common/utils.go index 4c57419a5..61a1f9877 100644 --- a/tss/common/utils.go +++ b/tss/common/utils.go @@ -2,13 +2,21 @@ package common import ( "bytes" + "context" + "crypto/ecdsa" "math/big" + "time" "github.com/btcsuite/btcd/btcec" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/mantlenetworkio/mantle/l2geth/log" ) var ( @@ -138,3 +146,82 @@ func IsAddrExist(set []common.Address, find common.Address) bool { } return false } + +// Ensure we can actually connect l1 +func EnsureConnection(client *ethclient.Client) error { + t := time.NewTicker(1 * time.Second) + retries := 0 + defer t.Stop() + for ; true; <-t.C { + _, err := client.ChainID(context.Background()) + if err == nil { + break + } else { + retries += 1 + if retries > 90 { + return err + } + } + } + return nil +} + +func EstimateGas(client *ethclient.Client, prikey *ecdsa.PrivateKey,chainId *big.Int, ctx context.Context, tx *types.Transaction, rawContract *bind.BoundContract, to common.Address) (*types.Transaction, error) { + from := crypto.PubkeyToAddress(prikey.PublicKey) + + header, err := client.HeaderByNumber(ctx, nil) + if err != nil { + log.Error("failed to get header by l1client","err",err.Error()) + return nil, err + } + var gasPrice *big.Int + var gasTipCap *big.Int + var gasFeeCap *big.Int + if header.BaseFee == nil { + gasPrice, err = client.SuggestGasPrice(ctx) + if err != nil { + log.Error("cannot fetch gas price ", "err",err.Error()) + return nil, err + } + } else { + gasTipCap, err = client.SuggestGasTipCap(ctx) + if err != nil { + log.Warn("failed to SuggestGasTipCap, FallbackGasTipCap = big.NewInt(1500000000) ") + gasTipCap = big.NewInt(1500000000) + } + gasFeeCap = new(big.Int).Add( + gasTipCap, + new(big.Int).Mul(header.BaseFee, big.NewInt(2)), + ) + } + + msg := ethereum.CallMsg{ + From: from, + To: &to, + GasPrice: gasPrice, + GasTipCap: gasTipCap, + GasFeeCap: gasFeeCap, + Value: nil, + Data: tx.Data(), + } + + gasLimit, err := client.EstimateGas(ctx, msg) + if err != nil { + log.Error("failed to EstimateGas","err",err.Error()) + return nil, err + } + opts, err := bind.NewKeyedTransactorWithChainID(prikey, chainId) + if err != nil { + log.Error("failed to new ops in estimate gas function","err",err.Error()) + return nil, err + } + opts.Context = ctx + opts.NoSend = true + opts.Nonce = new(big.Int).SetUint64(tx.Nonce()) + + opts.GasTipCap = gasTipCap + opts.GasFeeCap = gasFeeCap + opts.GasLimit = 25 * gasLimit //add 20% buffer to gas limit + + return rawContract.RawTransact(opts, tx.Data()) +} diff --git a/tss/manager/cmd.go b/tss/manager/cmd.go index f349fd9c7..2e104cbbd 100644 --- a/tss/manager/cmd.go +++ b/tss/manager/cmd.go @@ -35,6 +35,9 @@ func Command() *cobra.Command { func run(cmd *cobra.Command) error { config := common.GetConfigFromCmd(cmd) log.Info("config info print", "SignedBatchesWindow", config.SignedBatchesWindow, "MinSignedInWindow", config.MinSignedInWindow) + if len(config.Manager.PrivateKey) == 0 { + return errors.New("need to config private key") + } wsServer, err := server.NewWSServer(config.Manager.WsAddr) if err != nil { return err diff --git a/tss/manager/manage.go b/tss/manager/manage.go index 39d73ac85..a2dcd6258 100644 --- a/tss/manager/manage.go +++ b/tss/manager/manage.go @@ -1,6 +1,8 @@ package manager import ( + "context" + "crypto/ecdsa" "encoding/hex" "encoding/json" "errors" @@ -18,6 +20,7 @@ import ( "github.com/ethereum/go-ethereum/ethclient" "github.com/influxdata/influxdb/pkg/slices" + "github.com/mantlenetworkio/mantle/l2geth/crypto" "github.com/mantlenetworkio/mantle/l2geth/log" tss "github.com/mantlenetworkio/mantle/tss/common" "github.com/mantlenetworkio/mantle/tss/index" @@ -27,13 +30,16 @@ import ( ) type Manager struct { - wsServer server.IWebsocketManager - tssQueryService types.TssQueryService - store types.ManagerStore - l1Cli *ethclient.Client - tssStakingSlashingCaller *tsh.TssStakingSlashingCaller - tssGroupManagerCaller *tgm.TssGroupManagerCaller - l1ConfirmBlocks int + wsServer server.IWebsocketManager + tssQueryService types.TssQueryService + store types.ManagerStore + l1Cli *ethclient.Client + privateKey *ecdsa.PrivateKey + chainId *big.Int + tssStakingSlashingAddress string + tssStakingSlashingCaller *tsh.TssStakingSlashingCaller + tssGroupManagerCaller *tgm.TssGroupManagerCaller + l1ConfirmBlocks int taskInterval time.Duration confirmReceiptTimeout time.Duration @@ -89,14 +95,27 @@ func NewManager(wsServer server.IWebsocketManager, if err != nil { return Manager{}, err } + privKey, err := crypto.HexToECDSA(config.Manager.PrivateKey) + if err != nil { + return Manager{}, err + } + + chainId, err := l1Cli.ChainID(context.Background()) + if err != nil { + return Manager{}, err + } + return Manager{ - wsServer: wsServer, - tssQueryService: tssQueryService, - store: store, - l1Cli: l1Cli, - l1ConfirmBlocks: config.L1ConfirmBlocks, - tssStakingSlashingCaller: tssStakingSlashingCaller, - tssGroupManagerCaller: tssGroupManagerCaller, + wsServer: wsServer, + tssQueryService: tssQueryService, + store: store, + l1Cli: l1Cli, + l1ConfirmBlocks: config.L1ConfirmBlocks, + tssStakingSlashingAddress: config.TssStakingSlashContractAddress, + tssStakingSlashingCaller: tssStakingSlashingCaller, + tssGroupManagerCaller: tssGroupManagerCaller, + privateKey: privKey, + chainId: chainId, taskInterval: taskIntervalDur, confirmReceiptTimeout: receiptConfirmTimeoutDur, diff --git a/tss/manager/sign.go b/tss/manager/sign.go index 1bdeef01f..20bfe5ca7 100644 --- a/tss/manager/sign.go +++ b/tss/manager/sign.go @@ -9,7 +9,6 @@ import ( "github.com/influxdata/influxdb/pkg/slices" "github.com/mantlenetworkio/mantle/l2geth/crypto" tmjson "github.com/tendermint/tendermint/libs/json" - "math/big" "strings" "sync" "time" @@ -97,28 +96,6 @@ func (m Manager) sign(ctx types.Context, request interface{}, digestBz []byte, m validSignResponse = &signResponse return } - - // if signing slashing, we chose a better gas price as the valid one - if validSignResponse == nil { - slashTxGasPrice, succ := new(big.Int).SetString(signResponse.SlashTxGasPrice, 10) - if !succ { - log.Error("wrong format of slashTxGasPrice") - return - } - signResponse.SlashTxGasPriceBigInt = slashTxGasPrice - validSignResponse = &signResponse - } else { - // if current gas price > last node gas price, replace it - slashTxGasPrice, succ := new(big.Int).SetString(signResponse.SlashTxGasPrice, 10) - if !succ { - log.Error("wrong format of slashTxGasPrice") - return - } - if slashTxGasPrice.Cmp(validSignResponse.SlashTxGasPriceBigInt) > 0 { - signResponse.SlashTxGasPriceBigInt = slashTxGasPrice - validSignResponse = &signResponse - } - } } else if resp.RpcResponse.Error.Code == tss.CulpritErrorCode { _, ok := responseNodes[resp.SourceNode] if ok { // ignore if handled diff --git a/tss/manager/sign_test.go b/tss/manager/sign_test.go index c7cc5546f..5d1f219bd 100644 --- a/tss/manager/sign_test.go +++ b/tss/manager/sign_test.go @@ -221,26 +221,8 @@ func TestSignSlash(t *testing.T) { }) afterMsgSent := func(request server.RequestMsg, respCh chan server.ResponseMsg) error { - var SlashTxGasPrice string - var SlashTxBytes []byte - switch request.TargetNode { - case "a": - SlashTxGasPrice = "100000" - SlashTxBytes = []byte("a") - case "b": - SlashTxGasPrice = "200000" - SlashTxBytes = []byte("b") - case "c": - SlashTxGasPrice = "500000" - SlashTxBytes = []byte("c") - case "d": - SlashTxGasPrice = "300000" - SlashTxBytes = []byte("d") - } signResp := tss.SignResponse{ Signature: signature, - SlashTxGasPrice: SlashTxGasPrice, - SlashTxBytes: SlashTxBytes, } rpcResp := tmtypes.NewRPCSuccessResponse(request.RpcRequest.ID, signResp) respCh <- server.ResponseMsg{ @@ -254,30 +236,14 @@ func TestSignSlash(t *testing.T) { require.NoError(t, err) require.Nil(t, culprits) require.EqualValues(t, signature, signResp.Signature) - require.EqualValues(t, signResp.SlashTxGasPriceBigInt.Int64(), 500000) - require.EqualValues(t, signResp.SlashTxBytes, []byte("c")) afterMsgSent = func(request server.RequestMsg, respCh chan server.ResponseMsg) error { if request.TargetNode == "c" { return nil } - var SlashTxGasPrice string - var SlashTxBytes []byte - switch request.TargetNode { - case "a": - SlashTxGasPrice = "100000" - SlashTxBytes = []byte("a") - case "b": - SlashTxGasPrice = "200000" - SlashTxBytes = []byte("b") - case "d": - SlashTxGasPrice = "300000" - SlashTxBytes = []byte("d") - } + signResp := tss.SignResponse{ Signature: signature, - SlashTxGasPrice: SlashTxGasPrice, - SlashTxBytes: SlashTxBytes, } rpcResp := tmtypes.NewRPCSuccessResponse(request.RpcRequest.ID, signResp) respCh <- server.ResponseMsg{ @@ -292,8 +258,6 @@ func TestSignSlash(t *testing.T) { require.NoError(t, err) require.Nil(t, culprits) require.EqualValues(t, signature, signResp.Signature) - require.EqualValues(t, signResp.SlashTxGasPriceBigInt.Int64(), 300000) - require.EqualValues(t, signResp.SlashTxBytes, []byte("d")) cost := time.Now().Sub(before) require.True(t, cost.Seconds()-manager.signTimeout.Seconds() >= 0) } diff --git a/tss/manager/slash.go b/tss/manager/slash.go index 396d7c001..89143c024 100644 --- a/tss/manager/slash.go +++ b/tss/manager/slash.go @@ -3,19 +3,31 @@ package manager import ( "context" "encoding/binary" + "errors" "math/big" + "strings" "sync" "time" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" eth "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/mantlenetworkio/mantle/l2geth/log" + "github.com/mantlenetworkio/mantle/tss/bindings/tsh" tss "github.com/mantlenetworkio/mantle/tss/common" "github.com/mantlenetworkio/mantle/tss/manager/types" "github.com/mantlenetworkio/mantle/tss/slash" ) +const ( + slashingMethodName = "slashing" + errMaxPriorityFeePerGasNotFound = "Method eth_maxPriorityFeePerGas not found" +) + +var FallbackGasTipCap = big.NewInt(1500000000) + var sendState = SendState{ states: make(map[[28]byte]string, 0), lock: &sync.Mutex{}, @@ -138,6 +150,8 @@ func (m Manager) handleSlashing(si slash.SlashingInfo) { approversAddress[i] = addr } digestBz, err := tss.SlashMsgHash(request.BatchIndex, request.Address, approversAddress, request.SignType) + mesTx, err := tss.SlashMsgBytes(si.BatchIndex, si.Address, approversAddress, request.SignType) + if err != nil { log.Error("failed to encode SlashMsg", "err", err) return @@ -149,15 +163,19 @@ func (m Manager) handleSlashing(si slash.SlashingInfo) { return } - if err = m.submitSlashing(signResp, si); err != nil { + if err = m.submitSlashing(signResp, si, mesTx); err != nil { log.Error("failed to submit slashing transaction", "error", err) } return } -func (m Manager) submitSlashing(signResp tss.SignResponse, si slash.SlashingInfo) error { +func (m Manager) submitSlashing(signResp tss.SignResponse, si slash.SlashingInfo, mesTx []byte) error { + txData, err := m.txBuilder(mesTx, signResp.Signature) + if err != nil { + return err + } tx := new(eth.Transaction) - if err := tx.UnmarshalBinary(signResp.SlashTxBytes); err != nil { + if err := tx.UnmarshalBinary(txData); err != nil { return err } if err := m.l1Cli.SendTransaction(context.Background(), tx); err != nil { @@ -213,6 +231,86 @@ func (m Manager) submitSlashing(signResp tss.SignResponse, si slash.SlashingInfo return nil } +func (m *Manager) txBuilder(txData, sig []byte) ([]byte, error) { + log.Info("connecting to layer one") + if err := tss.EnsureConnection(m.l1Cli); err != nil { + log.Error("Unable to connect to layer one", "err", err.Error()) + return nil, err + } + if len(m.tssStakingSlashingAddress) == 0 { + log.Error("tss staking slashing address is empty ") + return nil, errors.New("tss staking slashing address is empty") + } + address := common.HexToAddress(m.tssStakingSlashingAddress) + + //new raw contract + parsed, err := abi.JSON(strings.NewReader(tsh.TssStakingSlashingABI)) + if err != nil { + log.Error("Unable to new parsed from slash contract abi", "err", err.Error()) + return nil, err + } + //get staking slash contract abi + tshABI, err := tsh.TssStakingSlashingMetaData.GetAbi() + if err != nil { + log.Error("Unable to get tss staking slashing ABI", "err", err.Error()) + return nil, err + } + + rawSlashContract := bind.NewBoundContract(address, parsed, m.l1Cli, m.l1Cli, m.l1Cli) + dataBytes, err := tss.SlashBytes(txData, sig) + if err != nil { + log.Error("failed to pack slash bytes", "err", err.Error()) + return nil, err + } + slashingID := tshABI.Methods[slashingMethodName].ID + calldata := append(slashingID, dataBytes...) + + opts, err := bind.NewKeyedTransactorWithChainID(m.privateKey, m.chainId) + if err != nil { + log.Error("failed to new keyed transactor", "err", err.Error()) + return nil, err + } + ctx := context.Background() + if opts.Context == nil { + opts.Context = ctx + } + from := crypto.PubkeyToAddress(m.privateKey.PublicKey) + nonce64, err := m.l1Cli.NonceAt(ctx, from, nil) + if err != nil { + log.Error(" unable to get current nonce", "address", + from) + return nil, err + } + log.Info("Current nonce is ", "nonce", nonce64) + nonce := new(big.Int).SetUint64(nonce64) + opts.Nonce = nonce + opts.NoSend = true + + tx, err := rawSlashContract.RawTransact(opts, calldata) + if err != nil { + if strings.Contains(err.Error(), errMaxPriorityFeePerGasNotFound) { + opts.GasTipCap = FallbackGasTipCap + tx, err = rawSlashContract.RawTransact(opts, calldata) + if err != nil { + log.Error("failed to build slashing transaction tx!", "err", err.Error()) + return nil, err + } + } else { + log.Error("failed to build slashing transaction tx!", "err", err.Error()) + return nil, err + } + } + + newTx, err := tss.EstimateGas(m.l1Cli, m.privateKey, m.chainId, ctx, tx, rawSlashContract, address) + + txBinary, err := newTx.MarshalBinary() + if err != nil { + log.Error("failed to get marshal binary from transaction tx", "err", err.Error()) + return nil, err + } + return txBinary, nil +} + type SendState struct { states map[[28]byte]string lock *sync.Mutex diff --git a/tss/node/signer/sign_slash.go b/tss/node/signer/sign_slash.go index 7d42ff148..53d09763a 100644 --- a/tss/node/signer/sign_slash.go +++ b/tss/node/signer/sign_slash.go @@ -3,15 +3,10 @@ package signer import ( "encoding/json" "errors" - "math/big" "strings" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" ethc "github.com/ethereum/go-ethereum/common" - "github.com/mantlenetworkio/mantle/tss/bindings/tsh" tsscommon "github.com/mantlenetworkio/mantle/tss/common" - "github.com/rs/zerolog" tdtypes "github.com/tendermint/tendermint/rpc/jsonrpc/types" ) @@ -71,7 +66,6 @@ func (p *Processor) SignSlash() { nodesaddrs[i] = addr } hashTx, err := tsscommon.SlashMsgHash(requestBody.BatchIndex, requestBody.Address, nodesaddrs, requestBody.SignType) - mesTx, err := tsscommon.SlashMsgBytes(requestBody.BatchIndex, requestBody.Address, nodesaddrs, requestBody.SignType) if err != nil { logger.Err(err).Msg("failed to encode SlashMsg") RpcResponse := tdtypes.NewRPCErrorResponse(req.ID, 201, "failed", err.Error()) @@ -99,18 +93,9 @@ func (p *Processor) SignSlash() { } continue } - txData, gasPrice, err := p.txBuilder(mesTx, data, logger) - if err != nil { - logger.Err(err).Msg("failed to txbuilder slash tranction") - errorRes := tdtypes.NewRPCErrorResponse(req.ID, 201, "sign failed", err.Error()) - p.wsClient.SendMsg(errorRes) - continue - } signResponse := tsscommon.SignResponse{ Signature: data, - SlashTxBytes: txData, - SlashTxGasPrice: gasPrice.String(), } RpcResponse := tdtypes.NewRPCSuccessResponse(req.ID, signResponse) @@ -154,82 +139,3 @@ func (p *Processor) removeWaitSlashMsg(msg tsscommon.SlashRequest) { } } } - -func (p *Processor) txBuilder(txData, sig []byte, logger zerolog.Logger) ([]byte, *big.Int, error) { - logger.Info().Msg("connecting to layer one") - if err := ensureConnection(p.l1Client); err != nil { - logger.Err(err).Msg("Unable to connect to layer one") - return nil, nil, err - } - if len(p.tssStakingSlashingAddress) == 0 { - logger.Error().Msg("tss staking slashing address is empty ") - return nil, nil, errors.New("tss staking slashing address is empty") - } - address := ethc.HexToAddress(p.tssStakingSlashingAddress) - - //new raw contract - parsed, err := abi.JSON(strings.NewReader(tsh.TssStakingSlashingABI)) - if err != nil { - logger.Err(err).Msg("Unable to new parsed from slash contract abi") - return nil, nil, err - } - //get staking slash contract abi - tshABI, err := tsh.TssStakingSlashingMetaData.GetAbi() - if err != nil { - logger.Err(err).Msg("Unable to get tss staking slashing ABI") - return nil, nil, err - } - - rawSlashContract := bind.NewBoundContract(address, parsed, p.l1Client, p.l1Client, p.l1Client) - dataBytes, err := tsscommon.SlashBytes(txData, sig) - if err != nil { - logger.Err(err).Msg("failed to pack slash bytes") - return nil, nil, err - } - slashingID := tshABI.Methods[slashingMethodName].ID - calldata := append(slashingID, dataBytes...) - - opts, err := bind.NewKeyedTransactorWithChainID(p.privateKey, p.chainId) - if err != nil { - p.logger.Err(err).Msg("failed to new keyed transactor") - return nil, nil, err - } - if opts.Context == nil { - opts.Context = p.ctx - } - - nonce64, err := p.l1Client.NonceAt(p.ctx, p.address, nil) - if err != nil { - p.logger.Err(err).Msgf("%s unable to get current nonce", - p.address) - return nil, nil, err - } - p.logger.Info().Msgf("Current nonce is %d", nonce64) - nonce := new(big.Int).SetUint64(nonce64) - opts.Nonce = nonce - opts.NoSend = true - - tx, err := rawSlashContract.RawTransact(opts, calldata) - if err != nil { - if strings.Contains(err.Error(), errMaxPriorityFeePerGasNotFound) { - opts.GasTipCap = FallbackGasTipCap - tx, err = rawSlashContract.RawTransact(opts, calldata) - if err != nil { - logger.Err(err).Msg("failed to build slashing transaction tx!") - return nil, nil, err - } - } else { - logger.Err(err).Msg("failed to build slashing transaction tx!") - return nil, nil, err - } - } - - newTx, err := p.EstimateGas(p.ctx, tx, rawSlashContract, address) - - txBinary, err := newTx.MarshalBinary() - if err != nil { - logger.Err(err).Msg("failed to get marshal binary from transaction tx") - return nil, nil, err - } - return txBinary, newTx.GasPrice(), nil -}