aboutsummaryrefslogtreecommitdiffstats
path: root/core/vm
diff options
context:
space:
mode:
authorWei-Ning Huang <w@dexon.org>2018-12-18 20:25:58 +0800
committerWei-Ning Huang <w@dexon.org>2019-04-09 21:32:54 +0800
commita6fd9c42d0d2632961f1f8adfe9db85ac125d294 (patch)
tree329aa6351559fc38db674879265ca3102ca74e43 /core/vm
parent2e36ada5739437b6860d3978ac3e19f4073d94be (diff)
downloaddexon-a6fd9c42d0d2632961f1f8adfe9db85ac125d294.tar
dexon-a6fd9c42d0d2632961f1f8adfe9db85ac125d294.tar.gz
dexon-a6fd9c42d0d2632961f1f8adfe9db85ac125d294.tar.bz2
dexon-a6fd9c42d0d2632961f1f8adfe9db85ac125d294.tar.lz
dexon-a6fd9c42d0d2632961f1f8adfe9db85ac125d294.tar.xz
dexon-a6fd9c42d0d2632961f1f8adfe9db85ac125d294.tar.zst
dexon-a6fd9c42d0d2632961f1f8adfe9db85ac125d294.zip
core: vm: add undelegate fund lockup mechanism (#94)
Only allow a user to withdraw funds after a certain lockup period. This way, the fund of a bad actor could be confiscated before he could escape.
Diffstat (limited to 'core/vm')
-rw-r--r--core/vm/governance.go198
-rw-r--r--core/vm/governance_test.go77
2 files changed, 235 insertions, 40 deletions
diff --git a/core/vm/governance.go b/core/vm/governance.go
index 8c6f70a04..f423c4ca3 100644
--- a/core/vm/governance.go
+++ b/core/vm/governance.go
@@ -165,6 +165,10 @@ const GovernanceABIJSON = `
{
"name": "url",
"type": "string"
+ },
+ {
+ "name": "unstaked",
+ "type": "bool"
}
],
"payable": false,
@@ -253,6 +257,10 @@ const GovernanceABIJSON = `
{
"name": "value",
"type": "uint256"
+ },
+ {
+ "name": "undelegated_at",
+ "type": "uint256"
}
],
"payable": false,
@@ -443,6 +451,20 @@ const GovernanceABIJSON = `
},
{
"constant": true,
+ "inputs": [],
+ "name": "lockupPeriod",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
"inputs": [
{
"name": "",
@@ -568,6 +590,10 @@ const GovernanceABIJSON = `
"type": "uint256"
},
{
+ "name": "LockupPeriod",
+ "type": "uint256"
+ },
+ {
"name": "BlockReward",
"type": "uint256"
},
@@ -807,6 +833,20 @@ const GovernanceABIJSON = `
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "NodeAddress",
+ "type": "address"
+ }
+ ],
+ "name": "withdraw",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
}
]
`
@@ -958,6 +998,12 @@ func RunGovernanceContract(evm *EVM, input []byte, contract *Contract) (ret []by
return nil, errExecutionReverted
}
return g.updateConfiguration(&cfg)
+ case "withdraw":
+ address := common.Address{}
+ if err := method.Inputs.Unpack(&address, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ return g.withdraw(address)
// --------------------------------
// Solidity auto generated methods.
@@ -1087,6 +1133,12 @@ func RunGovernanceContract(evm *EVM, input []byte, contract *Contract) (ret []by
return nil, errExecutionReverted
}
return res, nil
+ case "lockupPeriod":
+ res, err := method.Outputs.Pack(g.state.LockupPeriod())
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
case "minBlockInterval":
res, err := method.Outputs.Pack(g.state.MinBlockInterval())
if err != nil {
@@ -1180,6 +1232,7 @@ const (
dkgFinalizedsCountLoc
ownerLoc
minStakeLoc
+ lockupPeriodLoc
blockRewardLoc
blockGasLimitLoc
numChainsLoc
@@ -1360,6 +1413,7 @@ func (s *GovernanceStateHelper) PushRoundHeight(height *big.Int) {
// string email;
// string location;
// string url;
+// bool unstaked;
// }
//
// Node[] nodes;
@@ -1372,9 +1426,10 @@ type nodeInfo struct {
Email string
Location string
Url string
+ Unstaked bool
}
-const nodeStructSize = 7
+const nodeStructSize = 8
func (s *GovernanceStateHelper) LenNodes() *big.Int {
return s.getStateBigInt(big.NewInt(nodesLoc))
@@ -1414,6 +1469,10 @@ func (s *GovernanceStateHelper) Node(index *big.Int) *nodeInfo {
loc = new(big.Int).Add(elementBaseLoc, big.NewInt(6))
node.Url = string(s.readBytes(loc))
+ // Unstaked.
+ loc = new(big.Int).Add(elementBaseLoc, big.NewInt(7))
+ node.Unstaked = s.getStateBigInt(loc).Cmp(big.NewInt(0)) > 0
+
return node
}
func (s *GovernanceStateHelper) PushNode(n *nodeInfo) {
@@ -1454,6 +1513,14 @@ func (s *GovernanceStateHelper) UpdateNode(index *big.Int, n *nodeInfo) {
// Url.
loc = new(big.Int).Add(elementBaseLoc, big.NewInt(6))
s.writeBytes(loc, []byte(n.Url))
+
+ // Unstaked.
+ loc = new(big.Int).Add(elementBaseLoc, big.NewInt(7))
+ val := big.NewInt(0)
+ if n.Unstaked {
+ val = big.NewInt(1)
+ }
+ s.setStateBigInt(loc, val)
}
func (s *GovernanceStateHelper) PopLastNode() {
// Decrease length by 1.
@@ -1499,14 +1566,16 @@ func (s *GovernanceStateHelper) DeleteNodesOffset(addr common.Address) {
// address node;
// address owner;
// uint256 value;
+// uint256 undelegated_at;
// }
type delegatorInfo struct {
- Owner common.Address
- Value *big.Int
+ Owner common.Address
+ Value *big.Int
+ UndelegatedAt *big.Int
}
-const delegatorStructSize = 2
+const delegatorStructSize = 3
// mapping(address => Delegator[]) public delegators;
func (s *GovernanceStateHelper) LenDelegators(nodeAddr common.Address) *big.Int {
@@ -1528,6 +1597,10 @@ func (s *GovernanceStateHelper) Delegator(nodeAddr common.Address, offset *big.I
loc = new(big.Int).Add(elementBaseLoc, big.NewInt(1))
delegator.Value = s.getStateBigInt(loc)
+ // UndelegatedAt.
+ loc = new(big.Int).Add(elementBaseLoc, big.NewInt(2))
+ delegator.UndelegatedAt = s.getStateBigInt(loc)
+
return delegator
}
func (s *GovernanceStateHelper) PushDelegator(nodeAddr common.Address, delegator *delegatorInfo) {
@@ -1550,6 +1623,10 @@ func (s *GovernanceStateHelper) UpdateDelegator(nodeAddr common.Address, offset
// Value.
loc = new(big.Int).Add(elementBaseLoc, big.NewInt(1))
s.setStateBigInt(loc, delegator.Value)
+
+ // UndelegatedAt.
+ loc = new(big.Int).Add(elementBaseLoc, big.NewInt(2))
+ s.setStateBigInt(loc, delegator.UndelegatedAt)
}
func (s *GovernanceStateHelper) PopLastDelegator(nodeAddr common.Address) {
// Decrease length by 1.
@@ -1558,7 +1635,10 @@ func (s *GovernanceStateHelper) PopLastDelegator(nodeAddr common.Address) {
loc := s.getMapLoc(big.NewInt(delegatorsLoc), nodeAddr.Bytes())
s.setStateBigInt(loc, newArrayLength)
- s.UpdateDelegator(nodeAddr, newArrayLength, &delegatorInfo{Value: big.NewInt(0)})
+ s.UpdateDelegator(nodeAddr, newArrayLength, &delegatorInfo{
+ Value: big.NewInt(0),
+ UndelegatedAt: big.NewInt(0),
+ })
}
// mapping(address => mapping(address => uint256)) delegatorsOffset;
@@ -1676,17 +1756,16 @@ func (s *GovernanceStateHelper) SetOwner(newOwner common.Address) {
func (s *GovernanceStateHelper) MinStake() *big.Int {
return s.getStateBigInt(big.NewInt(minStakeLoc))
}
-func (s *GovernanceStateHelper) SetMinStake(stake *big.Int) {
- s.setStateBigInt(big.NewInt(minStakeLoc), stake)
+
+// uint256 public lockupPeriod;
+func (s *GovernanceStateHelper) LockupPeriod() *big.Int {
+ return s.getStateBigInt(big.NewInt(lockupPeriodLoc))
}
// uint256 public blockReward;
func (s *GovernanceStateHelper) BlockReward() *big.Int {
return s.getStateBigInt(big.NewInt(blockRewardLoc))
}
-func (s *GovernanceStateHelper) SetBlockReward(reward *big.Int) {
- s.setStateBigInt(big.NewInt(blockRewardLoc), reward)
-}
// uint256 public blockGasLimit;
func (s *GovernanceStateHelper) BlockGasLimit() *big.Int {
@@ -1764,6 +1843,7 @@ const phiRatioMultiplier = 1000000.0
func (s *GovernanceStateHelper) Configuration() *params.DexconConfig {
return &params.DexconConfig{
MinStake: s.getStateBigInt(big.NewInt(minStakeLoc)),
+ LockupPeriod: s.getStateBigInt(big.NewInt(lockupPeriodLoc)).Uint64(),
BlockReward: s.getStateBigInt(big.NewInt(blockRewardLoc)),
BlockGasLimit: s.getStateBigInt(big.NewInt(blockGasLimitLoc)).Uint64(),
NumChains: uint32(s.getStateBigInt(big.NewInt(numChainsLoc)).Uint64()),
@@ -1781,6 +1861,7 @@ func (s *GovernanceStateHelper) Configuration() *params.DexconConfig {
// UpdateConfiguration updates system configuration.
func (s *GovernanceStateHelper) UpdateConfiguration(cfg *params.DexconConfig) {
s.setStateBigInt(big.NewInt(minStakeLoc), cfg.MinStake)
+ s.setStateBigInt(big.NewInt(lockupPeriodLoc), big.NewInt(int64(cfg.LockupPeriod)))
s.setStateBigInt(big.NewInt(blockRewardLoc), cfg.BlockReward)
s.setStateBigInt(big.NewInt(blockGasLimitLoc), big.NewInt(int64(cfg.BlockGasLimit)))
s.setStateBigInt(big.NewInt(numChainsLoc), big.NewInt(int64(cfg.NumChains)))
@@ -1796,6 +1877,7 @@ func (s *GovernanceStateHelper) UpdateConfiguration(cfg *params.DexconConfig) {
type rawConfigStruct struct {
MinStake *big.Int
+ LockupPeriod *big.Int
BlockReward *big.Int
BlockGasLimit *big.Int
NumChains *big.Int
@@ -1812,6 +1894,7 @@ type rawConfigStruct struct {
// UpdateConfigurationRaw updates system configuration.
func (s *GovernanceStateHelper) UpdateConfigurationRaw(cfg *rawConfigStruct) {
s.setStateBigInt(big.NewInt(minStakeLoc), cfg.MinStake)
+ s.setStateBigInt(big.NewInt(lockupPeriodLoc), cfg.LockupPeriod)
s.setStateBigInt(big.NewInt(blockRewardLoc), cfg.BlockReward)
s.setStateBigInt(big.NewInt(blockGasLimitLoc), cfg.BlockGasLimit)
s.setStateBigInt(big.NewInt(numChainsLoc), cfg.NumChains)
@@ -2082,8 +2165,9 @@ func (g *GovernanceContract) delegate(nodeAddr common.Address) ([]byte, error) {
// Push delegator record.
offset = g.state.LenDelegators(nodeAddr)
g.state.PushDelegator(nodeAddr, &delegatorInfo{
- Owner: caller,
- Value: value,
+ Owner: caller,
+ Value: value,
+ UndelegatedAt: big.NewInt(0),
})
g.state.PutDelegatorOffset(nodeAddr, caller, offset)
g.state.emitDelegated(nodeAddr, caller, value)
@@ -2146,18 +2230,62 @@ func (g *GovernanceContract) stake(
return g.useGas(100000)
}
-func (g *GovernanceContract) undelegateHelper(nodeAddr, owner common.Address) ([]byte, error) {
+func (g *GovernanceContract) undelegateHelper(nodeAddr, caller common.Address) ([]byte, error) {
nodeOffset := g.state.NodesOffset(nodeAddr)
if nodeOffset.Cmp(big.NewInt(0)) < 0 {
return nil, errExecutionReverted
}
- offset := g.state.DelegatorsOffset(nodeAddr, owner)
+ offset := g.state.DelegatorsOffset(nodeAddr, caller)
if offset.Cmp(big.NewInt(0)) < 0 {
return nil, errExecutionReverted
}
delegator := g.state.Delegator(nodeAddr, offset)
+
+ // Set undelegate time.
+ delegator.UndelegatedAt = g.evm.Time
+ g.state.UpdateDelegator(nodeAddr, offset, delegator)
+
+ // Subtract from the total staked of node.
+ node := g.state.Node(nodeOffset)
+ node.Staked = new(big.Int).Sub(node.Staked, delegator.Value)
+ g.state.UpdateNode(nodeOffset, node)
+
+ g.state.emitUndelegated(nodeAddr, caller)
+
+ return g.useGas(100000)
+}
+
+func (g *GovernanceContract) undelegate(nodeAddr common.Address) ([]byte, error) {
+ return g.undelegateHelper(nodeAddr, g.contract.Caller())
+}
+
+func (g *GovernanceContract) withdraw(nodeAddr common.Address) ([]byte, error) {
+ caller := g.contract.Caller()
+
+ nodeOffset := g.state.NodesOffset(nodeAddr)
+ if nodeOffset.Cmp(big.NewInt(0)) < 0 {
+ return nil, errExecutionReverted
+ }
+
+ offset := g.state.DelegatorsOffset(nodeAddr, caller)
+ if offset.Cmp(big.NewInt(0)) < 0 {
+ return nil, errExecutionReverted
+ }
+
+ delegator := g.state.Delegator(nodeAddr, offset)
+
+ // Not yet undelegated.
+ if delegator.UndelegatedAt.Cmp(big.NewInt(0)) == 0 {
+ return g.penalize()
+ }
+
+ unlockTime := new(big.Int).Add(delegator.UndelegatedAt, g.state.LockupPeriod())
+ if g.evm.Time.Cmp(unlockTime) <= 0 {
+ return g.penalize()
+ }
+
length := g.state.LenDelegators(nodeAddr)
lastIndex := new(big.Int).Sub(length, big.NewInt(1))
@@ -2167,25 +2295,30 @@ func (g *GovernanceContract) undelegateHelper(nodeAddr, owner common.Address) ([
g.state.UpdateDelegator(nodeAddr, offset, lastNode)
g.state.PutDelegatorOffset(nodeAddr, lastNode.Owner, offset)
}
- g.state.DeleteDelegatorsOffset(nodeAddr, owner)
+ g.state.DeleteDelegatorsOffset(nodeAddr, caller)
g.state.PopLastDelegator(nodeAddr)
- // Subtract from the total staked of node.
- node := g.state.Node(nodeOffset)
- node.Staked = new(big.Int).Sub(node.Staked, delegator.Value)
- g.state.UpdateNode(nodeOffset, node)
-
// Return the staked fund.
if !g.transfer(GovernanceContractAddress, delegator.Owner, delegator.Value) {
return nil, errExecutionReverted
}
- g.state.emitUndelegated(nodeAddr, owner)
- return g.useGas(100000)
-}
+ // We are the last delegator to withdraw the fund, remove the node info.
+ if g.state.LenDelegators(nodeAddr).Cmp(big.NewInt(0)) == 0 {
+ length := g.state.LenNodes()
+ lastIndex := new(big.Int).Sub(length, big.NewInt(1))
-func (g *GovernanceContract) undelegate(nodeAddr common.Address) ([]byte, error) {
- return g.undelegateHelper(nodeAddr, g.contract.Caller())
+ // Delete the node.
+ if offset.Cmp(lastIndex) != 0 {
+ lastNode := g.state.Node(lastIndex)
+ g.state.UpdateNode(offset, lastNode)
+ g.state.PutNodesOffset(lastNode.Owner, offset)
+ }
+ g.state.DeleteNodesOffset(nodeAddr)
+ g.state.PopLastNode()
+ }
+
+ return g.useGas(100000)
}
func (g *GovernanceContract) unstake() ([]byte, error) {
@@ -2206,17 +2339,10 @@ func (g *GovernanceContract) unstake() ([]byte, error) {
i = i.Sub(i, big.NewInt(1))
}
- length := g.state.LenNodes()
- lastIndex := new(big.Int).Sub(length, big.NewInt(1))
-
- // Delete the node.
- if offset.Cmp(lastIndex) != 0 {
- lastNode := g.state.Node(lastIndex)
- g.state.UpdateNode(offset, lastNode)
- g.state.PutNodesOffset(lastNode.Owner, offset)
- }
- g.state.DeleteNodesOffset(caller)
- g.state.PopLastNode()
+ // Mark node as unstaked.
+ node := g.state.Node(offset)
+ node.Unstaked = true
+ g.state.UpdateNode(offset, node)
g.state.emitUnstaked(caller)
diff --git a/core/vm/governance_test.go b/core/vm/governance_test.go
index 7718e99d2..018306992 100644
--- a/core/vm/governance_test.go
+++ b/core/vm/governance_test.go
@@ -103,6 +103,8 @@ func (g *GovernanceContractTestSuite) SetupTest() {
g.s = &GovernanceStateHelper{stateDB}
config := params.TestnetChainConfig.Dexcon
+ config.LockupPeriod = 1000
+
g.config = config
// Give governance contract balance so it will not be deleted because of being an empty state object.
@@ -155,7 +157,7 @@ func (g *GovernanceContractTestSuite) call(caller common.Address, input []byte,
}
return 0, false
},
- Time: big.NewInt(time.Now().UnixNano() / 1000000000),
+ Time: big.NewInt(time.Now().UnixNano() / 1000000),
BlockNumber: big.NewInt(0),
}
@@ -180,7 +182,7 @@ func (g *GovernanceContractTestSuite) TestTransferOwnership() {
g.Require().Equal(addr, g.s.Owner())
}
-func (g *GovernanceContractTestSuite) TestStakeUnstakeWithoutDelegators() {
+func (g *GovernanceContractTestSuite) TestStakeUnstakeWithoutExtraDelegators() {
privKey, addr := g.newPrefundAccount()
pk := crypto.FromECDSAPub(&privKey.PublicKey)
@@ -210,6 +212,17 @@ func (g *GovernanceContractTestSuite) TestStakeUnstakeWithoutDelegators() {
g.Require().Nil(err)
_, err = g.call(addr, input, big.NewInt(0))
g.Require().Nil(err)
+ g.Require().Equal(1, int(g.s.LenDelegators(addr).Uint64()))
+ g.Require().Equal(1, int(g.s.LenNodes().Uint64()))
+
+ // Wait for lockup time than withdraw.
+ time.Sleep(time.Second * 2)
+ input, err = abiObject.Pack("withdraw", addr)
+ g.Require().Nil(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().Nil(err)
+
+ g.Require().Equal(0, int(g.s.LenDelegators(addr).Uint64()))
g.Require().Equal(0, int(g.s.LenNodes().Uint64()))
// Stake 2 nodes, and unstake the first then the second.
@@ -235,6 +248,12 @@ func (g *GovernanceContractTestSuite) TestStakeUnstakeWithoutDelegators() {
g.Require().Nil(err)
_, err = g.call(addr2, input, big.NewInt(0))
g.Require().Nil(err)
+ time.Sleep(time.Second * 2)
+ input, err = abiObject.Pack("withdraw", addr2)
+ g.Require().Nil(err)
+ _, err = g.call(addr2, input, big.NewInt(0))
+ g.Require().Nil(err)
+
g.Require().Equal(1, int(g.s.LenNodes().Uint64()))
g.Require().Equal("Test1", g.s.Node(big.NewInt(0)).Name)
g.Require().Equal(-1, int(g.s.NodesOffset(addr2).Int64()))
@@ -244,6 +263,12 @@ func (g *GovernanceContractTestSuite) TestStakeUnstakeWithoutDelegators() {
g.Require().Nil(err)
_, err = g.call(addr, input, big.NewInt(0))
g.Require().Nil(err)
+ time.Sleep(time.Second * 2)
+ input, err = abiObject.Pack("withdraw", addr)
+ g.Require().Nil(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().Nil(err)
+
g.Require().Equal(0, int(g.s.LenNodes().Uint64()))
g.Require().Equal(-1, int(g.s.NodesOffset(addr).Int64()))
g.Require().Equal(-1, int(g.s.DelegatorsOffset(addr, addr).Int64()))
@@ -309,16 +334,49 @@ func (g *GovernanceContractTestSuite) TestDelegateUndelegate() {
g.Require().Nil(err)
_, err = g.call(addrDelegator, input, big.NewInt(0))
g.Require().Nil(err)
+
+ // Withdraw within lockup time should fail.
+ input, err = abiObject.Pack("withdraw", addr)
+ g.Require().Nil(err)
+ _, err = g.call(addrDelegator, input, big.NewInt(0))
+ g.Require().NotNil(err)
+
+ g.Require().Equal(3, int(g.s.LenDelegators(addr).Uint64()))
+ g.Require().Equal(balanceBeforeUnDelegate, g.stateDB.GetBalance(addrDelegator))
+ g.Require().NotEqual(-1, int(g.s.DelegatorsOffset(addr, addrDelegator).Int64()))
+
+ // Wait for lockup time than withdraw.
+ time.Sleep(time.Second * 2)
+ input, err = abiObject.Pack("withdraw", addr)
+ g.Require().Nil(err)
+ _, err = g.call(addrDelegator, input, big.NewInt(0))
+ g.Require().Nil(err)
+
g.Require().Equal(2, int(g.s.LenDelegators(addr).Uint64()))
g.Require().Equal(new(big.Int).Add(balanceBeforeUnDelegate, amount), g.stateDB.GetBalance(addrDelegator))
g.Require().Equal(-1, int(g.s.DelegatorsOffset(addr, addrDelegator).Int64()))
+ // Withdraw when their is no delegation should fail.
+ time.Sleep(time.Second)
+ input, err = abiObject.Pack("withdraw", addr)
+ g.Require().Nil(err)
+ _, err = g.call(addrDelegator, input, big.NewInt(0))
+ g.Require().NotNil(err)
+
// Undelegate addrDelegator2.
balanceBeforeUnDelegate = g.stateDB.GetBalance(addrDelegator2)
input, err = abiObject.Pack("undelegate", addr)
g.Require().Nil(err)
_, err = g.call(addrDelegator2, input, big.NewInt(0))
g.Require().Nil(err)
+
+ // Wait for lockup time than withdraw.
+ time.Sleep(time.Second * 2)
+ input, err = abiObject.Pack("withdraw", addr)
+ g.Require().Nil(err)
+ _, err = g.call(addrDelegator2, input, big.NewInt(0))
+ g.Require().Nil(err)
+
g.Require().Equal(1, int(g.s.LenDelegators(addr).Uint64()))
g.Require().Equal(new(big.Int).Add(balanceBeforeUnDelegate, amount), g.stateDB.GetBalance(addrDelegator2))
g.Require().Equal(-1, int(g.s.DelegatorsOffset(addr, addrDelegator2).Int64()))
@@ -327,7 +385,7 @@ func (g *GovernanceContractTestSuite) TestDelegateUndelegate() {
g.Require().Equal(0, len(g.s.QualifiedNodes()))
}
-func (g *GovernanceContractTestSuite) TestUnstakeWithDelegators() {
+func (g *GovernanceContractTestSuite) TestUnstakeWithExtraDelegators() {
privKey, addr := g.newPrefundAccount()
pk := crypto.FromECDSAPub(&privKey.PublicKey)
@@ -372,6 +430,17 @@ func (g *GovernanceContractTestSuite) TestUnstakeWithDelegators() {
g.Require().Nil(err)
_, err = g.call(addr, input, big.NewInt(0))
g.Require().Nil(err)
+
+ time.Sleep(time.Second * 2)
+ input, err = abiObject.Pack("withdraw", addr)
+ g.Require().Nil(err)
+ _, err = g.call(addr, input, big.NewInt(0))
+ g.Require().Nil(err)
+ _, err = g.call(addrDelegator, input, big.NewInt(0))
+ g.Require().Nil(err)
+ _, err = g.call(addrDelegator2, input, big.NewInt(0))
+ g.Require().Nil(err)
+
g.Require().Equal(0, int(g.s.LenDelegators(addr).Uint64()))
g.Require().Equal(0, int(g.s.LenNodes().Uint64()))
@@ -386,7 +455,7 @@ func (g *GovernanceContractTestSuite) TestUpdateConfiguration() {
_, addr := g.newPrefundAccount()
input, err := abiObject.Pack("updateConfiguration",
- new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1e5)),
+ new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1e5)), big.NewInt(1000),
big.NewInt(1e18), big.NewInt(8000000), big.NewInt(6), big.NewInt(250), big.NewInt(2500),
big.NewInt(0), big.NewInt(667000), big.NewInt(4), big.NewInt(4), big.NewInt(600000), big.NewInt(900))
g.Require().Nil(err)