From 4432f9b42d24d29dd1adf354e7217025d4819976 Mon Sep 17 00:00:00 2001 From: Zero Ekkusu <94782988+ZeroEkkusu@users.noreply.github.com> Date: Mon, 8 Apr 2024 12:37:53 +0200 Subject: [PATCH 01/92] feat: transition to POL --- .../staking/stakeManager/StakeManager.sol | 601 +++++++++--------- 1 file changed, 299 insertions(+), 302 deletions(-) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 6feca104..5f0ed069 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -23,13 +23,7 @@ import {IGovernance} from "../../common/governance/IGovernance.sol"; import {Initializable} from "../../common/mixin/Initializable.sol"; import {StakeManagerExtension} from "./StakeManagerExtension.sol"; -contract StakeManager is - StakeManagerStorage, - Initializable, - IStakeManager, - DelegateProxyForwarder, - StakeManagerStorageExtension -{ +contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, DelegateProxyForwarder, StakeManagerStorageExtension { using SafeMath for uint256; using Merkle for bytes32; using RLPReader for bytes; @@ -91,18 +85,18 @@ contract StakeManager is validatorShareFactory = ValidatorShareFactory(_validatorShareFactory); _transferOwnership(_owner); - WITHDRAWAL_DELAY = (2**13); // unit: epoch + WITHDRAWAL_DELAY = (2 ** 13); // unit: epoch currentEpoch = 1; dynasty = 886; // unit: epoch 50 days - CHECKPOINT_REWARD = 20188 * (10**18); // update via governance - minDeposit = (10**18); // in ERC20 token - minHeimdallFee = (10**18); // in ERC20 token + CHECKPOINT_REWARD = 20_188 * (10 ** 18); // update via governance + minDeposit = (10 ** 18); // in ERC20 token + minHeimdallFee = (10 ** 18); // in ERC20 token checkPointBlockInterval = 1024; signerUpdateLimit = 100; validatorThreshold = 7; //128 NFTCounter = 1; - auctionPeriod = (2**13) / 4; // 1 week in epochs + auctionPeriod = (2 ** 13) / 4; // 1 week in epochs proposerBonus = 10; // 10 % of total rewards delegationEnabled = true; } @@ -117,15 +111,14 @@ contract StakeManager is } /** - Public View Methods + * Public View Methods */ - function getRegistry() public view returns (address) { return registry; } /** - @dev Owner of validator slot NFT + * @dev Owner of validator slot NFT */ function ownerOf(uint256 tokenId) public view returns (address) { return NFTContract.ownerOf(tokenId); @@ -162,7 +155,7 @@ contract StakeManager is function validatorReward(uint256 validatorId) public view returns (uint256) { uint256 _validatorReward; if (validators[validatorId].deactivationEpoch == 0) { - (_validatorReward, ) = _evaluateValidatorAndDelegationReward(validatorId); + (_validatorReward,) = _evaluateValidatorAndDelegationReward(validatorId); } return validators[validatorId].reward.add(_validatorReward).sub(INITIALIZED_AMOUNT); } @@ -180,26 +173,25 @@ contract StakeManager is } function isValidator(uint256 validatorId) public view returns (bool) { - return - _isValidator( - validators[validatorId].status, - validators[validatorId].amount, - validators[validatorId].deactivationEpoch, - currentEpoch - ); + return _isValidator(validators[validatorId].status, validators[validatorId].amount, validators[validatorId].deactivationEpoch, currentEpoch); } /** - Governance Methods + * Governance Methods */ - function setDelegationEnabled(bool enabled) public onlyGovernance { delegationEnabled = enabled; } + // @note forceUnstake // Housekeeping function. @todo remove later function forceUnstake(uint256 validatorId) external onlyGovernance { - _unstake(validatorId, currentEpoch); + _unstake(validatorId, currentEpoch, false); + } + + // @note + function forceUnstakeLegacy(uint256 validatorId) external onlyGovernance { + _unstake(validatorId, currentEpoch, true); } function setCurrentEpoch(uint256 _currentEpoch) external onlyGovernance { @@ -212,7 +204,7 @@ contract StakeManager is } /** - @dev Change the number of validators required to allow a passed header root + * @dev Change the number of validators required to allow a passed header root */ function updateValidatorThreshold(uint256 newThreshold) public onlyGovernance { require(newThreshold != 0); @@ -231,11 +223,10 @@ contract StakeManager is CHECKPOINT_REWARD = newReward; } - function updateCheckpointRewardParams( - uint256 _rewardDecreasePerCheckpoint, - uint256 _maxRewardedCheckpoints, - uint256 _checkpointRewardDelta - ) public onlyGovernance { + function updateCheckpointRewardParams(uint256 _rewardDecreasePerCheckpoint, uint256 _maxRewardedCheckpoints, uint256 _checkpointRewardDelta) + public + onlyGovernance + { delegatedFwd( extensionCode, abi.encodeWithSelector( @@ -250,14 +241,7 @@ contract StakeManager is // New implementation upgrade function migrateValidatorsData(uint256 validatorIdFrom, uint256 validatorIdTo) public onlyOwner { - delegatedFwd( - extensionCode, - abi.encodeWithSelector( - StakeManagerExtension(extensionCode).migrateValidatorsData.selector, - validatorIdFrom, - validatorIdTo - ) - ); + delegatedFwd(extensionCode, abi.encodeWithSelector(StakeManagerExtension(extensionCode).migrateValidatorsData.selector, validatorIdFrom, validatorIdTo)); } function insertSigners(address[] memory _signers) public onlyOwner { @@ -265,7 +249,7 @@ contract StakeManager is } /** - @dev Users must exit before this update or all funds may get lost + * @dev Users must exit before this update or all funds may get lost */ function updateValidatorContractAddress(uint256 validatorId, address newContractAddress) public onlyGovernance { require(IValidatorShare(newContractAddress).owner() == address(this)); @@ -301,27 +285,18 @@ contract StakeManager is minHeimdallFee = _minHeimdallFee; } - function drainValidatorShares( - uint256 validatorId, - address tokenAddr, - address payable destination, - uint256 amount - ) external onlyGovernance { + function drainValidatorShares(uint256 validatorId, address tokenAddr, address payable destination, uint256 amount) external onlyGovernance { address contractAddr = validators[validatorId].contractAddress; require(contractAddr != address(0x0)); IValidatorShare(contractAddr).drain(tokenAddr, destination, amount); } + // @note drain function drain(address destination, uint256 amount) external onlyGovernance { - _transferToken(destination, amount); + _transferToken(destination, amount, false); } - function reinitialize( - address _NFTContract, - address _stakingLogger, - address _validatorShareFactory, - address _extensionCode - ) external onlyGovernance { + function reinitialize(address _NFTContract, address _stakingLogger, address _validatorShareFactory, address _extensionCode) external onlyGovernance { require(isContract(_extensionCode)); eventsHub = address(0x0); extensionCode = _extensionCode; @@ -331,27 +306,36 @@ contract StakeManager is } /** - Public Methods + * Public Methods */ - + // @note topUpForFee function topUpForFee(address user, uint256 heimdallFee) public onlyWhenUnlocked { - _transferAndTopUp(user, msg.sender, heimdallFee, 0); + _transferAndTopUp(user, msg.sender, heimdallFee, 0, false); } - function claimFee( - uint256 accumFeeAmount, - uint256 index, - bytes memory proof - ) public { + // @note + function topUpForFeeLegacy(address user, uint256 heimdallFee) public onlyWhenUnlocked { + _transferAndTopUp(user, msg.sender, heimdallFee, 0, true); + } + + // @note claimFee + function claimFee(uint256 accumFeeAmount, uint256 index, bytes memory proof) public { + _claimFee(accumFeeAmount, index, proof, false); + } + + // @note + function claimFeeLegacy(uint256 accumFeeAmount, uint256 index, bytes memory proof) public { + _claimFee(accumFeeAmount, index, proof, true); + } + + // @note + function _claimFee(uint256 accumFeeAmount, uint256 index, bytes memory proof, bool legacy) internal { //Ignoring other params because rewards' distribution is on chain - require( - keccak256(abi.encode(msg.sender, accumFeeAmount)).checkMembership(index, accountStateRoot, proof), - "Wrong acc proof" - ); + require(keccak256(abi.encode(msg.sender, accumFeeAmount)).checkMembership(index, accountStateRoot, proof), "Wrong acc proof"); uint256 withdrawAmount = accumFeeAmount.sub(userFeeExit[msg.sender]); _claimFee(msg.sender, withdrawAmount); userFeeExit[msg.sender] = accumFeeAmount; - _transferToken(msg.sender, withdrawAmount); + _transferToken(msg.sender, withdrawAmount, legacy); } function totalStakedFor(address user) external view returns (uint256) { @@ -361,39 +345,26 @@ contract StakeManager is return validators[NFTContract.tokenOfOwnerByIndex(user, 0)].amount; } - function startAuction( - uint256 validatorId, - uint256 amount, - bool _acceptDelegation, - bytes calldata _signerPubkey - ) external onlyWhenUnlocked { + function startAuction(uint256 validatorId, uint256 amount, bool _acceptDelegation, bytes calldata _signerPubkey) external onlyWhenUnlocked { delegatedFwd( extensionCode, - abi.encodeWithSelector( - StakeManagerExtension(extensionCode).startAuction.selector, - validatorId, - amount, - _acceptDelegation, - _signerPubkey - ) + abi.encodeWithSelector(StakeManagerExtension(extensionCode).startAuction.selector, validatorId, amount, _acceptDelegation, _signerPubkey) ); } - function confirmAuctionBid( - uint256 validatorId, - uint256 heimdallFee /** for new validator */ - ) external onlyWhenUnlocked { + function confirmAuctionBid(uint256 validatorId, uint256 heimdallFee) + /** + * for new validator + */ + external + onlyWhenUnlocked + { delegatedFwd( - extensionCode, - abi.encodeWithSelector( - StakeManagerExtension(extensionCode).confirmAuctionBid.selector, - validatorId, - heimdallFee, - address(this) - ) + extensionCode, abi.encodeWithSelector(StakeManagerExtension(extensionCode).confirmAuctionBid.selector, validatorId, heimdallFee, address(this)) ); } + // @note dethroneAndStake function dethroneAndStake( address auctionUser, uint256 heimdallFee, @@ -402,78 +373,140 @@ contract StakeManager is bool acceptDelegation, bytes calldata signerPubkey ) external { + _dethroneAndStake(auctionUser, heimdallFee, validatorId, auctionAmount, acceptDelegation, signerPubkey, false); + } + + // @note + function dethroneAndStakeLegacy( + address auctionUser, + uint256 heimdallFee, + uint256 validatorId, + uint256 auctionAmount, + bool acceptDelegation, + bytes calldata signerPubkey + ) external { + _dethroneAndStake(auctionUser, heimdallFee, validatorId, auctionAmount, acceptDelegation, signerPubkey, true); + } + + // @note + function _dethroneAndStake( + address auctionUser, + uint256 heimdallFee, + uint256 validatorId, + uint256 auctionAmount, + bool acceptDelegation, + bytes memory signerPubkey, + bool legacy + ) internal { require(msg.sender == address(this), "not allowed"); // dethrone - _transferAndTopUp(auctionUser, auctionUser, heimdallFee, 0); - _unstake(validatorId, currentEpoch); + _transferAndTopUp(auctionUser, auctionUser, heimdallFee, 0, legacy); + _unstake(validatorId, currentEpoch, legacy); uint256 newValidatorId = _stakeFor(auctionUser, auctionAmount, acceptDelegation, signerPubkey); logger.logConfirmAuction(newValidatorId, validatorId, auctionAmount); } + // @note unstake function unstake(uint256 validatorId) external onlyStaker(validatorId) { + _unstake(validatorId, false); + } + + // @note + function unstakeLegacy(uint256 validatorId) external onlyStaker(validatorId) { + _unstake(validatorId, true); + } + + // @note + function _unstake(uint256 validatorId, bool legacy) internal { require(validatorAuction[validatorId].amount == 0); Status status = validators[validatorId].status; require( - validators[validatorId].activationEpoch > 0 && - validators[validatorId].deactivationEpoch == 0 && - (status == Status.Active || status == Status.Locked) + validators[validatorId].activationEpoch > 0 && validators[validatorId].deactivationEpoch == 0 + && (status == Status.Active || status == Status.Locked) ); uint256 exitEpoch = currentEpoch.add(1); // notice period - _unstake(validatorId, exitEpoch); + _unstake(validatorId, exitEpoch, legacy); } - function transferFunds( - uint256 validatorId, - uint256 amount, - address delegator - ) external returns (bool) { - require( - validators[validatorId].contractAddress == msg.sender || - Registry(registry).getSlashingManagerAddress() == msg.sender, - "not allowed" - ); - return token.transfer(delegator, amount); + // @note transferFunds + function transferFunds(uint256 validatorId, uint256 amount, address delegator) external returns (bool) { + return _transferFunds(validatorId, amount, delegator, false); } - function delegationDeposit( - uint256 validatorId, - uint256 amount, - address delegator - ) external onlyDelegation(validatorId) returns (bool) { - return token.transferFrom(delegator, address(this), amount); + // @note + function transferFundsLegacy(uint256 validatorId, uint256 amount, address delegator) external returns (bool) { + return _transferFunds(validatorId, amount, delegator, true); } - function stakeFor( - address user, - uint256 amount, - uint256 heimdallFee, - bool acceptDelegation, - bytes memory signerPubkey - ) public onlyWhenUnlocked { + // @note + function _transferFunds(uint256 validatorId, uint256 amount, address delegator, bool legacy) internal returns (bool) { + require(validators[validatorId].contractAddress == msg.sender || Registry(registry).getSlashingManagerAddress() == msg.sender, "not allowed"); + if (legacy) _convertPolToMatic(amount); + IERC20 token_ = _getToken(legacy); + return token_.transfer(delegator, amount); + } + + // @note delegationDeposit + function delegationDeposit(uint256 validatorId, uint256 amount, address delegator) external onlyDelegation(validatorId) returns (bool) { + return _delegationDeposit(amount, delegator, false); + } + + // @note + function delegationDepositLegacy(uint256 validatorId, uint256 amount, address delegator) external onlyDelegation(validatorId) returns (bool) { + return _delegationDeposit(amount, delegator, true); + } + + // @note + function _delegationDeposit(uint256 amount, address delegator, bool legacy) internal returns (bool) { + IERC20 token_ = _getToken(legacy); + token_.transferFrom(delegator, address(this), amount); + if (legacy) _convertMaticToPol(amount); + return true; + } + + // @note stakeFor + function stakeFor(address user, uint256 amount, uint256 heimdallFee, bool acceptDelegation, bytes memory signerPubkey) public onlyWhenUnlocked { + _stakeFor(user, amount, heimdallFee, acceptDelegation, signerPubkey, false); + } + + // @note + function stakeForLegacy(address user, uint256 amount, uint256 heimdallFee, bool acceptDelegation, bytes memory signerPubkey) public onlyWhenUnlocked { + _stakeFor(user, amount, heimdallFee, acceptDelegation, signerPubkey, true); + } + + // @note + function _stakeFor(address user, uint256 amount, uint256 heimdallFee, bool acceptDelegation, bytes memory signerPubkey, bool legacy) internal { require(currentValidatorSetSize() < validatorThreshold, "no more slots"); require(amount >= minDeposit, "not enough deposit"); - _transferAndTopUp(user, msg.sender, heimdallFee, amount); + _transferAndTopUp(user, msg.sender, heimdallFee, amount, legacy); _stakeFor(user, amount, acceptDelegation, signerPubkey); } + // @note unstakeClaim function unstakeClaim(uint256 validatorId) public onlyStaker(validatorId) { + _unstakeClaim(validatorId, false); + } + + // @note + function unstakeClaimLegacy(uint256 validatorId) public onlyStaker(validatorId) { + _unstakeClaim(validatorId, true); + } + + // @note + function _unstakeClaim(uint256 validatorId, bool legacy) internal { uint256 deactivationEpoch = validators[validatorId].deactivationEpoch; // can only claim stake back after WITHDRAWAL_DELAY - require( - deactivationEpoch > 0 && - deactivationEpoch.add(WITHDRAWAL_DELAY) <= currentEpoch && - validators[validatorId].status != Status.Unstaked - ); + require(deactivationEpoch > 0 && deactivationEpoch.add(WITHDRAWAL_DELAY) <= currentEpoch && validators[validatorId].status != Status.Unstaked); uint256 amount = validators[validatorId].amount; uint256 newTotalStaked = totalStaked.sub(amount); totalStaked = newTotalStaked; // claim last checkpoint reward if it was signed by validator - _liquidateRewards(validatorId, msg.sender); + _liquidateRewards(validatorId, msg.sender, legacy); NFTContract.burn(validatorId); @@ -484,19 +517,26 @@ contract StakeManager is signerToValidator[validators[validatorId].signer] = INCORRECT_VALIDATOR_ID; validators[validatorId].status = Status.Unstaked; - _transferToken(msg.sender, amount); + _transferToken(msg.sender, amount, legacy); logger.logUnstaked(msg.sender, validatorId, amount, newTotalStaked); } - function restake( - uint256 validatorId, - uint256 amount, - bool stakeRewards - ) public onlyWhenUnlocked onlyStaker(validatorId) { + // @note restake + function restake(uint256 validatorId, uint256 amount, bool stakeRewards) public onlyWhenUnlocked onlyStaker(validatorId) { + _restake(validatorId, amount, stakeRewards, false); + } + + // @note + function restakeLegacy(uint256 validatorId, uint256 amount, bool stakeRewards) public onlyWhenUnlocked onlyStaker(validatorId) { + _restake(validatorId, amount, stakeRewards, true); + } + + // @note + function _restake(uint256 validatorId, uint256 amount, bool stakeRewards, bool legacy) internal { require(validators[validatorId].deactivationEpoch == 0, "No restaking"); if (amount > 0) { - _transferTokenFrom(msg.sender, address(this), amount); + _transferTokenFrom(msg.sender, address(this), amount, legacy); } _updateRewards(validatorId); @@ -516,16 +556,23 @@ contract StakeManager is logger.logRestaked(validatorId, validators[validatorId].amount, newTotalStaked); } + // @note withdrawRewards function withdrawRewards(uint256 validatorId) public onlyStaker(validatorId) { + _withdrawRewards(validatorId, false); + } + + // @note + function withdrawRewardsLegacy(uint256 validatorId) public onlyStaker(validatorId) { + _withdrawRewards(validatorId, true); + } + + // @note + function _withdrawRewards(uint256 validatorId, bool legacy) internal { _updateRewards(validatorId); - _liquidateRewards(validatorId, msg.sender); + _liquidateRewards(validatorId, msg.sender, legacy); } - function migrateDelegation( - uint256 fromValidatorId, - uint256 toValidatorId, - uint256 amount - ) public { + function migrateDelegation(uint256 fromValidatorId, uint256 toValidatorId, uint256 amount) public { // allow to move to any non-foundation node require(toValidatorId > 7, "Invalid migration"); IValidatorShare(validators[fromValidatorId].contractAddress).migrateOut(msg.sender, amount); @@ -540,12 +587,13 @@ contract StakeManager is uint256 deactivationEpoch = validators[validatorId].deactivationEpoch; - if (deactivationEpoch == 0) { // modify timeline only if validator didn't unstake + if (deactivationEpoch == 0) { + // modify timeline only if validator didn't unstake updateTimeline(amount, 0, 0); - } else if (deactivationEpoch > currentEpoch) { // validator just unstaked, need to wait till next checkpoint + } else if (deactivationEpoch > currentEpoch) { + // validator just unstaked, need to wait till next checkpoint revert("unstaking"); } - if (amount >= 0) { increaseValidatorDelegatedAmount(validatorId, uint256(amount)); @@ -570,8 +618,8 @@ contract StakeManager is address currentSigner = validators[validatorId].signer; // update signer event logger.logSignerChange(validatorId, currentSigner, signer, signerPubkey); - - if (validators[validatorId].deactivationEpoch == 0) { + + if (validators[validatorId].deactivationEpoch == 0) { // didn't unstake, swap signer in the list _removeSigner(currentSigner); _insertSigner(signer); @@ -585,13 +633,11 @@ contract StakeManager is latestSignerUpdateEpoch[validatorId] = _currentEpoch; } - function checkSignatures( - uint256 blockInterval, - bytes32 voteHash, - bytes32 stateRoot, - address proposer, - uint256[3][] calldata sigs - ) external onlyRootChain returns (uint256) { + function checkSignatures(uint256 blockInterval, bytes32 voteHash, bytes32 stateRoot, address proposer, uint256[3][] calldata sigs) + external + onlyRootChain + returns (uint256) + { uint256 _currentEpoch = currentEpoch; uint256 signedStakePower; address lastAdd; @@ -648,30 +694,22 @@ contract StakeManager is // find the rest of validators without signature unsignedCtx = _fillUnsignedValidators(unsignedCtx, address(0)); - return - _increaseRewardAndAssertConsensus( - blockInterval, - proposer, - signedStakePower, - stateRoot, - unsignedCtx.unsignedValidators, - unsignedCtx.unsignedValidatorIndex, - unstakeCtx.deactivatedValidators, - unstakeCtx.validatorIndex - ); + return _increaseRewardAndAssertConsensus( + blockInterval, + proposer, + signedStakePower, + stateRoot, + unsignedCtx.unsignedValidators, + unsignedCtx.unsignedValidatorIndex, + unstakeCtx.deactivatedValidators, + unstakeCtx.validatorIndex + ); } function updateCommissionRate(uint256 validatorId, uint256 newCommissionRate) external onlyStaker(validatorId) { _updateRewards(validatorId); - delegatedFwd( - extensionCode, - abi.encodeWithSelector( - StakeManagerExtension(extensionCode).updateCommissionRate.selector, - validatorId, - newCommissionRate - ) - ); + delegatedFwd(extensionCode, abi.encodeWithSelector(StakeManagerExtension(extensionCode).updateCommissionRate.selector, validatorId, newCommissionRate)); } function withdrawDelegatorsReward(uint256 validatorId) public onlyDelegation(validatorId) returns (uint256) { @@ -682,6 +720,7 @@ contract StakeManager is return totalReward; } + // @note slash function slash(bytes calldata _slashingInfoList) external returns (uint256) { require(Registry(registry).getSlashingManagerAddress() == msg.sender, "Not slash manager"); @@ -703,11 +742,7 @@ contract StakeManager is address delegationContract = validators[validatorId].contractAddress; if (delegationContract != address(0x0)) { uint256 delSlashedAmount = - IValidatorShare(delegationContract).slash( - validators[validatorId].amount, - validators[validatorId].delegatedAmount, - _amount - ); + IValidatorShare(delegationContract).slash(validators[validatorId].amount, validators[validatorId].delegatedAmount, _amount); _amount = _amount.sub(delSlashedAmount); } @@ -715,7 +750,7 @@ contract StakeManager is validators[validatorId].amount = validatorStakeSlashed; if (validatorStakeSlashed == 0) { - _unstake(validatorId, currentEpoch); + _unstake(validatorId, currentEpoch, false); } else if (slashData[2].toBoolean()) { jailedAmount = jailedAmount.add(_jail(validatorId, 1)); valJailed++; @@ -752,11 +787,7 @@ contract StakeManager is logger.logUnjailed(validatorId, signer); } - function updateTimeline( - int256 amount, - int256 stakerCount, - uint256 targetEpoch - ) internal { + function updateTimeline(int256 amount, int256 stakerCount, uint256 targetEpoch) internal { if (targetEpoch == 0) { // update total stake and validator count if (amount > 0) { @@ -779,12 +810,7 @@ contract StakeManager is function updateValidatorDelegation(bool delegation) external { uint256 validatorId = signerToValidator[msg.sender]; require( - _isValidator( - validators[validatorId].status, - validators[validatorId].amount, - validators[validatorId].deactivationEpoch, - currentEpoch - ), + _isValidator(validators[validatorId].status, validators[validatorId].amount, validators[validatorId].deactivationEpoch, currentEpoch), "not validator" ); @@ -795,9 +821,8 @@ contract StakeManager is } /** - Private Methods + * Private Methods */ - function _getAndAssertSigner(bytes memory pub) private view returns (address) { require(pub.length == 64, "not pub"); address signer = address(uint160(uint256(keccak256(pub)))); @@ -805,20 +830,11 @@ contract StakeManager is return signer; } - function _isValidator( - Status status, - uint256 amount, - uint256 deactivationEpoch, - uint256 _currentEpoch - ) private pure returns (bool) { + function _isValidator(Status status, uint256 amount, uint256 deactivationEpoch, uint256 _currentEpoch) private pure returns (bool) { return (amount > 0 && (deactivationEpoch == 0 || deactivationEpoch > _currentEpoch) && status == Status.Active); } - function _fillUnsignedValidators(UnsignedValidatorsContext memory context, address signer) - private - view - returns(UnsignedValidatorsContext memory) - { + function _fillUnsignedValidators(UnsignedValidatorsContext memory context, address signer) private view returns (UnsignedValidatorsContext memory) { while (context.validatorIndex < context.totalValidators && context.validators[context.validatorIndex] != signer) { context.unsignedValidators[context.unsignedValidatorIndex] = signerToValidator[context.validators[context.validatorIndex]]; context.unsignedValidatorIndex++; @@ -829,11 +845,7 @@ contract StakeManager is return context; } - function _calculateCheckpointReward( - uint256 blockInterval, - uint256 signedStakePower, - uint256 currentTotalStake - ) internal returns (uint256) { + function _calculateCheckpointReward(uint256 blockInterval, uint256 signedStakePower, uint256 currentTotalStake) internal returns (uint256) { // checkpoint rewards are based on BlockInterval multiplied on `CHECKPOINT_REWARD` // for bigger checkpoints reward is reduced by rewardDecreasePerCheckpoint for each subsequent interval @@ -850,7 +862,7 @@ contract StakeManager is if (prevBlockInterval != 0) { // give more reward for faster and less for slower checkpoint uint256 delta = (ckpReward * checkpointRewardDelta / CHK_REWARD_PRECISION); - + if (prevBlockInterval > fullIntervals) { // checkpoint is faster ckpReward += delta; @@ -858,7 +870,7 @@ contract StakeManager is ckpReward -= delta; } } - + prevBlockInterval = fullIntervals; } @@ -869,7 +881,9 @@ contract StakeManager is uint256 _rewardDecreasePerCheckpoint = rewardDecreasePerCheckpoint; // calculate reward for full intervals - reward = ckpReward.mul(fullIntervals).sub(ckpReward.mul(((fullIntervals - 1) * fullIntervals / 2).mul(_rewardDecreasePerCheckpoint)).div(CHK_REWARD_PRECISION)); + reward = ckpReward.mul(fullIntervals).sub( + ckpReward.mul(((fullIntervals - 1) * fullIntervals / 2).mul(_rewardDecreasePerCheckpoint)).div(CHK_REWARD_PRECISION) + ); // adjust block interval, in case last interval is not full blockInterval = blockInterval.sub(fullIntervals.mul(targetBlockInterval)); // adjust checkpoint reward by the amount it suppose to decrease @@ -906,8 +920,7 @@ contract StakeManager is // update stateMerkleTree root for accounts balance on heimdall chain accountStateRoot = stateRoot; - uint256 newRewardPerStake = - rewardPerStake.add(reward.sub(_proposerBonus).mul(REWARD_PRECISION).div(signedStakePower)); + uint256 newRewardPerStake = rewardPerStake.add(reward.sub(_proposerBonus).mul(REWARD_PRECISION).div(signedStakePower)); // evaluate rewards for validator who did't sign and set latest reward per stake to new value to avoid them from getting new rewards. _updateValidatorsRewards(unsignedValidators, totalUnsignedValidators, newRewardPerStake); @@ -922,22 +935,14 @@ contract StakeManager is return reward; } - function _updateValidatorsRewards( - uint256[] memory unsignedValidators, - uint256 totalUnsignedValidators, - uint256 newRewardPerStake - ) private { + function _updateValidatorsRewards(uint256[] memory unsignedValidators, uint256 totalUnsignedValidators, uint256 newRewardPerStake) private { uint256 currentRewardPerStake = rewardPerStake; for (uint256 i = 0; i < totalUnsignedValidators; ++i) { _updateRewardsAndCommit(unsignedValidators[i], currentRewardPerStake, newRewardPerStake); } } - function _updateRewardsAndCommit( - uint256 validatorId, - uint256 currentRewardPerStake, - uint256 newRewardPerStake - ) private { + function _updateRewardsAndCommit(uint256 validatorId, uint256 currentRewardPerStake, uint256 newRewardPerStake) private { uint256 deactivationEpoch = validators[validatorId].deactivationEpoch; if (deactivationEpoch != 0 && currentEpoch >= deactivationEpoch) { return; @@ -955,23 +960,10 @@ contract StakeManager is validatorId, validatorsStake, delegatedAmount, - _getEligibleValidatorReward( - validatorId, - combinedStakePower, - currentRewardPerStake, - initialRewardPerStake - ) + _getEligibleValidatorReward(validatorId, combinedStakePower, currentRewardPerStake, initialRewardPerStake) ); } else { - _increaseValidatorReward( - validatorId, - _getEligibleValidatorReward( - validatorId, - validatorsStake, - currentRewardPerStake, - initialRewardPerStake - ) - ); + _increaseValidatorReward(validatorId, _getEligibleValidatorReward(validatorId, validatorsStake, currentRewardPerStake, initialRewardPerStake)); } } @@ -984,12 +976,11 @@ contract StakeManager is _updateRewardsAndCommit(validatorId, rewardPerStake, rewardPerStake); } - function _getEligibleValidatorReward( - uint256 validatorId, - uint256 validatorStakePower, - uint256 currentRewardPerStake, - uint256 initialRewardPerStake - ) private pure returns (uint256) { + function _getEligibleValidatorReward(uint256 validatorId, uint256 validatorStakePower, uint256 currentRewardPerStake, uint256 initialRewardPerStake) + private + pure + returns (uint256) + { uint256 eligibleReward = currentRewardPerStake - initialRewardPerStake; return eligibleReward.mul(validatorStakePower).div(REWARD_PRECISION); } @@ -1000,15 +991,9 @@ contract StakeManager is } } - function _increaseValidatorRewardWithDelegation( - uint256 validatorId, - uint256 validatorsStake, - uint256 delegatedAmount, - uint256 reward - ) private { + function _increaseValidatorRewardWithDelegation(uint256 validatorId, uint256 validatorsStake, uint256 delegatedAmount, uint256 reward) private { uint256 combinedStakePower = delegatedAmount.add(validatorsStake); - (uint256 validatorReward, uint256 delegatorsReward) = - _getValidatorAndDelegationReward(validatorId, validatorsStake, reward, combinedStakePower); + (uint256 validatorReward, uint256 delegatorsReward) = _getValidatorAndDelegationReward(validatorId, validatorsStake, reward, combinedStakePower); if (delegatorsReward > 0) { validators[validatorId].delegatorsReward = validators[validatorId].delegatorsReward.add(delegatorsReward); @@ -1019,12 +1004,11 @@ contract StakeManager is } } - function _getValidatorAndDelegationReward( - uint256 validatorId, - uint256 validatorsStake, - uint256 reward, - uint256 combinedStakePower - ) internal view returns (uint256, uint256) { + function _getValidatorAndDelegationReward(uint256 validatorId, uint256 validatorsStake, uint256 reward, uint256 combinedStakePower) + internal + view + returns (uint256, uint256) + { if (combinedStakePower == 0) { return (0, 0); } @@ -1034,30 +1018,18 @@ contract StakeManager is // add validator commission from delegation reward uint256 commissionRate = validators[validatorId].commissionRate; if (commissionRate > 0) { - validatorReward = validatorReward.add( - reward.sub(validatorReward).mul(commissionRate).div(MAX_COMMISION_RATE) - ); + validatorReward = validatorReward.add(reward.sub(validatorReward).mul(commissionRate).div(MAX_COMMISION_RATE)); } uint256 delegatorsReward = reward.sub(validatorReward); return (validatorReward, delegatorsReward); } - function _evaluateValidatorAndDelegationReward(uint256 validatorId) - private - view - returns (uint256 validatorReward, uint256 delegatorsReward) - { + function _evaluateValidatorAndDelegationReward(uint256 validatorId) private view returns (uint256 validatorReward, uint256 delegatorsReward) { uint256 validatorsStake = validators[validatorId].amount; uint256 combinedStakePower = validatorsStake.add(validators[validatorId].delegatedAmount); uint256 eligibleReward = rewardPerStake - validators[validatorId].initialRewardPerStake; - return - _getValidatorAndDelegationReward( - validatorId, - validatorsStake, - eligibleReward.mul(combinedStakePower).div(REWARD_PRECISION), - combinedStakePower - ); + return _getValidatorAndDelegationReward(validatorId, validatorsStake, eligibleReward.mul(combinedStakePower).div(REWARD_PRECISION), combinedStakePower); } function _jail(uint256 validatorId, uint256 jailCheckpoints) internal returns (uint256) { @@ -1073,12 +1045,7 @@ contract StakeManager is return validators[validatorId].amount.add(validators[validatorId].delegatedAmount); } - function _stakeFor( - address user, - uint256 amount, - bool acceptDelegation, - bytes memory signerPubkey - ) internal returns (uint256) { + function _stakeFor(address user, uint256 amount, bool acceptDelegation, bytes memory signerPubkey) internal returns (uint256) { address signer = _getAndAssertSigner(signerPubkey); uint256 _currentEpoch = currentEpoch; uint256 validatorId = NFTCounter; @@ -1094,9 +1061,7 @@ contract StakeManager is deactivationEpoch: 0, jailTime: 0, signer: signer, - contractAddress: acceptDelegation - ? validatorShareFactory.create(validatorId, address(_logger), registry) - : address(0x0), + contractAddress: acceptDelegation ? validatorShareFactory.create(validatorId, address(_logger), registry) : address(0x0), status: Status.Active, commissionRate: 0, lastCommissionUpdate: 0, @@ -1120,7 +1085,7 @@ contract StakeManager is return validatorId; } - function _unstake(uint256 validatorId, uint256 exitEpoch) internal { + function _unstake(uint256 validatorId, uint256 exitEpoch, bool legacy) internal { // TODO: if validators unstake and slashed to 0, he will be forced to unstake again // must think how to handle it correctly _updateRewards(validatorId); @@ -1139,7 +1104,7 @@ contract StakeManager is } _removeSigner(validators[validatorId].signer); - _liquidateRewards(validatorId, validator); + _liquidateRewards(validatorId, validator, legacy); uint256 targetEpoch = exitEpoch <= currentEpoch ? 0 : exitEpoch; updateTimeline(-(int256(amount) + delegationAmount), -1, targetEpoch); @@ -1159,34 +1124,33 @@ contract StakeManager is currentEpoch = nextEpoch; } - function _liquidateRewards(uint256 validatorId, address validatorUser) private { + // @note _liquidateRewards + function _liquidateRewards(uint256 validatorId, address validatorUser, bool legacy) private { uint256 reward = validators[validatorId].reward.sub(INITIALIZED_AMOUNT); totalRewardsLiquidated = totalRewardsLiquidated.add(reward); validators[validatorId].reward = INITIALIZED_AMOUNT; - _transferToken(validatorUser, reward); + _transferToken(validatorUser, reward, legacy); logger.logClaimRewards(validatorId, reward, totalRewardsLiquidated); } - function _transferToken(address destination, uint256 amount) private { - require(token.transfer(destination, amount), "transfer failed"); + // @note _transferToken + function _transferToken(address destination, uint256 amount, bool legacy) private { + if (legacy) _convertPolToMatic(amount); + IERC20 token_ = _getToken(legacy); + require(token_.transfer(destination, amount), "transfer failed"); } - function _transferTokenFrom( - address from, - address destination, - uint256 amount - ) private { - require(token.transferFrom(from, destination, amount), "transfer from failed"); + // @note _transferTokenFrom + function _transferTokenFrom(address from, address destination, uint256 amount, bool legacy) private { + IERC20 token_ = _getToken(legacy); + require(token_.transferFrom(from, destination, amount), "transfer from failed"); + if (legacy) _convertMaticToPol(amount); } - function _transferAndTopUp( - address user, - address from, - uint256 fee, - uint256 additionalAmount - ) private { + // @note + function _transferAndTopUp(address user, address from, uint256 fee, uint256 additionalAmount, bool legacy) private { require(fee >= minHeimdallFee, "fee too small"); - _transferTokenFrom(from, address(this), fee.add(additionalAmount)); + _transferTokenFrom(from, address(this), fee.add(additionalAmount), legacy); totalHeimdallFee = totalHeimdallFee.add(fee); logger.logTopUpFee(user, fee); } @@ -1199,8 +1163,8 @@ contract StakeManager is function _insertSigner(address newSigner) internal { signers.push(newSigner); - uint lastIndex = signers.length - 1; - uint i = lastIndex; + uint256 lastIndex = signers.length - 1; + uint256 i = lastIndex; for (; i > 0; --i) { address signer = signers[i - 1]; if (signer < newSigner) { @@ -1230,4 +1194,37 @@ contract StakeManager is signers.length = totalSigners - 1; } + + // ------------------------------------------------------------------------ + // @note MATIC <=> POL CONVERSION + // ------------------------------------------------------------------------ + + IERC20 public tokenLegacy; // TODO Set MATIC and POL on reinitialization (setStakingToken). + IPolygonMigration migration; + + // NOTE Convert all. + function convertMaticToPol(uint256 amount) external onlyGovernance { + _convertMaticToPol(amount); + } + + function _convertMaticToPol(uint256 amount) internal { + require(tokenLegacy.balanceOf(address(this)) >= amount, "Insufficient MATIC balance"); + tokenLegacy.approve(address(migration), amount); + migration.migrate(amount); + } + + function _convertPolToMatic(uint256 amount) internal { + require(token.balanceOf(address(this)) >= amount, "Insufficient POL balance"); + token.approve(address(migration), amount); + migration.unmigrate(amount); + } + + function _getToken(bool legacy) internal view returns (IERC20 token_) { + token_ = !legacy ? token : tokenLegacy; + } +} + +interface IPolygonMigration { + function migrate(uint256 amount) external; + function unmigrate(uint256 amount) external; } From b6e19bea4f98afb799e429b840fb666f03f366c4 Mon Sep 17 00:00:00 2001 From: Zero Ekkusu <94782988+ZeroEkkusu@users.noreply.github.com> Date: Wed, 10 Apr 2024 14:55:44 +0200 Subject: [PATCH 02/92] feat(ValidatorShare): add legacy support --- .../staking/stakeManager/IStakeManager.sol | 48 ++-- .../staking/validatorShare/ValidatorShare.sol | 234 ++++++++++++------ 2 files changed, 174 insertions(+), 108 deletions(-) diff --git a/contracts/staking/stakeManager/IStakeManager.sol b/contracts/staking/stakeManager/IStakeManager.sol index 867030fc..c4876bdd 100644 --- a/contracts/staking/stakeManager/IStakeManager.sol +++ b/contracts/staking/stakeManager/IStakeManager.sol @@ -2,46 +2,23 @@ pragma solidity 0.5.17; contract IStakeManager { // validator replacement - function startAuction( - uint256 validatorId, - uint256 amount, - bool acceptDelegation, - bytes calldata signerPubkey - ) external; + function startAuction(uint256 validatorId, uint256 amount, bool acceptDelegation, bytes calldata signerPubkey) external; function confirmAuctionBid(uint256 validatorId, uint256 heimdallFee) external; - function transferFunds( - uint256 validatorId, - uint256 amount, - address delegator - ) external returns (bool); + function transferFunds(uint256 validatorId, uint256 amount, address delegator) external returns (bool); - function delegationDeposit( - uint256 validatorId, - uint256 amount, - address delegator - ) external returns (bool); + function delegationDeposit(uint256 validatorId, uint256 amount, address delegator) external returns (bool); function unstake(uint256 validatorId) external; function totalStakedFor(address addr) external view returns (uint256); - function stakeFor( - address user, - uint256 amount, - uint256 heimdallFee, - bool acceptDelegation, - bytes memory signerPubkey - ) public; + function stakeFor(address user, uint256 amount, uint256 heimdallFee, bool acceptDelegation, bytes memory signerPubkey) public; - function checkSignatures( - uint256 blockInterval, - bytes32 voteHash, - bytes32 stateRoot, - address proposer, - uint[3][] calldata sigs - ) external returns (uint256); + function checkSignatures(uint256 blockInterval, bytes32 voteHash, bytes32 stateRoot, address proposer, uint256[3][] calldata sigs) + external + returns (uint256); function updateValidatorState(uint256 validatorId, int256 amount) public; @@ -57,13 +34,13 @@ contract IStakeManager { function withdrawalDelay() public view returns (uint256); - function delegatedAmount(uint256 validatorId) public view returns(uint256); + function delegatedAmount(uint256 validatorId) public view returns (uint256); function decreaseValidatorDelegatedAmount(uint256 validatorId, uint256 amount) public; - function withdrawDelegatorsReward(uint256 validatorId) public returns(uint256); + function withdrawDelegatorsReward(uint256 validatorId) public returns (uint256); - function delegatorsReward(uint256 validatorId) public view returns(uint256); + function delegatorsReward(uint256 validatorId) public view returns (uint256); function dethroneAndStake( address auctionUser, @@ -73,4 +50,9 @@ contract IStakeManager { bool acceptDelegation, bytes calldata signerPubkey ) external; + + // @note MATIC POL conversion ⬇️ + + function transferFundsLegacy(uint256 validatorId, uint256 amount, address delegator) external returns (bool); + function delegationDepositLegacy(uint256 validatorId, uint256 amount, address delegator) external returns (bool); } diff --git a/contracts/staking/validatorShare/ValidatorShare.sol b/contracts/staking/validatorShare/ValidatorShare.sol index 68cdea8e..e3902e63 100644 --- a/contracts/staking/validatorShare/ValidatorShare.sol +++ b/contracts/staking/validatorShare/ValidatorShare.sol @@ -18,9 +18,9 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I uint256 constant EXCHANGE_RATE_PRECISION = 100; // maximum matic possible, even if rate will be 1 and all matic will be staken in one go, it will result in 10 ^ 58 shares - uint256 constant EXCHANGE_RATE_HIGH_PRECISION = 10**29; + uint256 constant EXCHANGE_RATE_HIGH_PRECISION = 10 ** 29; uint256 constant MAX_COMMISION_RATE = 100; - uint256 constant REWARD_PRECISION = 10**25; + uint256 constant REWARD_PRECISION = 10 ** 25; StakingInfo public stakingLogger; IStakeManager public stakeManager; @@ -49,25 +49,20 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I EventsHub public eventsHub; // onlyOwner will prevent this contract from initializing, since it's owner is going to be 0x0 address - function initialize( - uint256 _validatorId, - address _stakingLogger, - address _stakeManager - ) external initializer { + function initialize(uint256 _validatorId, address _stakingLogger, address _stakeManager) external initializer { validatorId = _validatorId; stakingLogger = StakingInfo(_stakingLogger); stakeManager = IStakeManager(_stakeManager); _transferOwnership(_stakeManager); _getOrCacheEventsHub(); - minAmount = 10**18; + minAmount = 10 ** 18; delegation = true; } /** - Public View Methods - */ - + * Public View Methods + */ function exchangeRate() public view returns (uint256) { uint256 totalShares = totalSupply(); uint256 precision = _getRatePrecision(); @@ -106,19 +101,45 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I } /** - Public Methods + * Public Methods */ + // @note buyVoucher + function buyVoucher(uint256 _amount, uint256 _minSharesToMint) public returns (uint256 amountToDeposit) { + return _buyVoucher(_amount, _minSharesToMint, false); + } + + // @note + function buyVoucherLegacy(uint256 _amount, uint256 _minSharesToMint) public returns (uint256 amountToDeposit) { + return _buyVoucher(_amount, _minSharesToMint, true); + } + + // @note + function _buyVoucher(uint256 _amount, uint256 _minSharesToMint, bool legacy) internal returns (uint256 amountToDeposit) { + _withdrawAndTransferReward(msg.sender, legacy); - function buyVoucher(uint256 _amount, uint256 _minSharesToMint) public returns(uint256 amountToDeposit) { - _withdrawAndTransferReward(msg.sender); - amountToDeposit = _buyShares(_amount, _minSharesToMint, msg.sender); - require(stakeManager.delegationDeposit(validatorId, amountToDeposit, msg.sender), "deposit failed"); - + require( + legacy + ? stakeManager.delegationDepositLegacy(validatorId, amountToDeposit, msg.sender) + : stakeManager.delegationDeposit(validatorId, amountToDeposit, msg.sender), + "deposit failed" + ); + return amountToDeposit; } - function restake() public returns(uint256, uint256) { + // @note restake + function restake() public returns (uint256, uint256) { + return _restake(false); + } + + // @note + function restakeLegacy() public returns (uint256, uint256) { + return _restake(true); + } + + // @note + function _restake(bool legacy) public returns (uint256, uint256) { address user = msg.sender; uint256 liquidReward = _withdrawReward(user); uint256 amountRestaked; @@ -131,21 +152,34 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I if (liquidReward > amountRestaked) { // return change to the user require( - stakeManager.transferFunds(validatorId, liquidReward - amountRestaked, user), + legacy + ? stakeManager.transferFundsLegacy(validatorId, liquidReward - amountRestaked, user) + : stakeManager.transferFunds(validatorId, liquidReward - amountRestaked, user), "Insufficent rewards" ); stakingLogger.logDelegatorClaimRewards(validatorId, user, liquidReward - amountRestaked); } - (uint256 totalStaked, ) = getTotalStake(user); + (uint256 totalStaked,) = getTotalStake(user); stakingLogger.logDelegatorRestaked(validatorId, user, totalStaked); } - + return (amountRestaked, liquidReward); } + // @note sellVoucher function sellVoucher(uint256 claimAmount, uint256 maximumSharesToBurn) public { - (uint256 shares, uint256 _withdrawPoolShare) = _sellVoucher(claimAmount, maximumSharesToBurn); + __sellVoucher(claimAmount, maximumSharesToBurn, false); + } + + // @note + function sellVoucherLegacy(uint256 claimAmount, uint256 maximumSharesToBurn) public { + __sellVoucher(claimAmount, maximumSharesToBurn, true); + } + + // @note + function __sellVoucher(uint256 claimAmount, uint256 maximumSharesToBurn, bool legacy) internal { + (uint256 shares, uint256 _withdrawPoolShare) = _sellVoucher(claimAmount, maximumSharesToBurn, legacy); DelegatorUnbond memory unbond = unbonds[msg.sender]; unbond.shares = unbond.shares.add(_withdrawPoolShare); @@ -158,13 +192,35 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I logger.logStakeUpdate(validatorId); } + // @note withdrawRewards function withdrawRewards() public { - uint256 rewards = _withdrawAndTransferReward(msg.sender); + _withdrawRewards(false); + } + + // @note + function withdrawRewardsLegacy() public { + _withdrawRewards(true); + } + + // @note + function _withdrawRewards(bool legacy) internal { + uint256 rewards = _withdrawAndTransferReward(msg.sender, legacy); require(rewards >= minAmount, "Too small rewards amount"); } + // @note migrateOut function migrateOut(address user, uint256 amount) external onlyOwner { - _withdrawAndTransferReward(user); + _migrateOut(user, amount, false); + } + + // @note + function migrateOutLegacy(address user, uint256 amount) external onlyOwner { + _migrateOut(user, amount, true); + } + + // @note + function _migrateOut(address user, uint256 amount, bool legacy) internal { + _withdrawAndTransferReward(user, legacy); (uint256 totalStaked, uint256 rate) = getTotalStake(user); require(totalStaked >= amount, "Migrating too much"); @@ -180,23 +236,41 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I stakingLogger.logDelegatorUnstaked(validatorId, user, amount); } + // @note migrateIn function migrateIn(address user, uint256 amount) external onlyOwner { - _withdrawAndTransferReward(user); + _migrateIn(user, amount, false); + } + + // @note + function migrateInLegacy(address user, uint256 amount) external onlyOwner { + _migrateIn(user, amount, true); + } + + // @note + function _migrateIn(address user, uint256 amount, bool legacy) internal { + _withdrawAndTransferReward(user, legacy); _buyShares(amount, 0, user); } + // @note unstakeClaimTokens function unstakeClaimTokens() public { + _unstakeClaimTokens(false); + } + + // @note + function unstakeClaimTokensLegacy() public { + _unstakeClaimTokens(true); + } + + // @note + function _unstakeClaimTokens(bool legacy) internal { DelegatorUnbond memory unbond = unbonds[msg.sender]; - uint256 amount = _unstakeClaimTokens(unbond); + uint256 amount = _unstakeClaimTokens(unbond, legacy); delete unbonds[msg.sender]; stakingLogger.logDelegatorUnstaked(validatorId, msg.sender, amount); } - function slash( - uint256 validatorStake, - uint256 delegatedAmount, - uint256 totalAmountToSlash - ) external onlyOwner returns (uint256) { + function slash(uint256 validatorStake, uint256 delegatedAmount, uint256 totalAmountToSlash) external onlyOwner returns (uint256) { uint256 _withdrawPool = withdrawPool; uint256 delegationAmount = delegatedAmount.add(_withdrawPool); if (delegationAmount == 0) { @@ -219,11 +293,7 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I delegation = _delegation; } - function drain( - address token, - address payable destination, - uint256 amount - ) external onlyOwner { + function drain(address token, address payable destination, uint256 amount) external onlyOwner { if (token == address(0x0)) { destination.transfer(amount); } else { @@ -232,18 +302,25 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I } /** - New shares exit API + * New shares exit API */ - + // @note sellVoucher_new function sellVoucher_new(uint256 claimAmount, uint256 maximumSharesToBurn) public { - (uint256 shares, uint256 _withdrawPoolShare) = _sellVoucher(claimAmount, maximumSharesToBurn); + _sellVoucher_new(claimAmount, maximumSharesToBurn, false); + } + + // @note + function sellVoucher_newLegacy(uint256 claimAmount, uint256 maximumSharesToBurn) public { + _sellVoucher_new(claimAmount, maximumSharesToBurn, true); + } + + // @note + function _sellVoucher_new(uint256 claimAmount, uint256 maximumSharesToBurn, bool legacy) public { + (uint256 shares, uint256 _withdrawPoolShare) = _sellVoucher(claimAmount, maximumSharesToBurn, legacy); uint256 unbondNonce = unbondNonces[msg.sender].add(1); - DelegatorUnbond memory unbond = DelegatorUnbond({ - shares: _withdrawPoolShare, - withdrawEpoch: stakeManager.epoch() - }); + DelegatorUnbond memory unbond = DelegatorUnbond({shares: _withdrawPoolShare, withdrawEpoch: stakeManager.epoch()}); unbonds_new[msg.sender][unbondNonce] = unbond; unbondNonces[msg.sender] = unbondNonce; @@ -251,18 +328,28 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I stakingLogger.logStakeUpdate(validatorId); } + // @note unstakeClaimTokens function unstakeClaimTokens_new(uint256 unbondNonce) public { + _unstakeClaimTokens_new(unbondNonce, false); + } + + // @note + function unstakeClaimTokens_newLegacy(uint256 unbondNonce) public { + _unstakeClaimTokens_new(unbondNonce, true); + } + + // @note + function _unstakeClaimTokens_new(uint256 unbondNonce, bool legacy) internal { DelegatorUnbond memory unbond = unbonds_new[msg.sender][unbondNonce]; - uint256 amount = _unstakeClaimTokens(unbond); + uint256 amount = _unstakeClaimTokens(unbond, legacy); delete unbonds_new[msg.sender][unbondNonce]; _getOrCacheEventsHub().logDelegatorUnstakedWithId(validatorId, msg.sender, amount, unbondNonce); } /** - Private Methods + * Private Methods */ - - function _getOrCacheEventsHub() private returns(EventsHub) { + function _getOrCacheEventsHub() private returns (EventsHub) { EventsHub _eventsHub = eventsHub; if (_eventsHub == EventsHub(0x0)) { _eventsHub = EventsHub(Registry(stakeManager.getRegistry()).contractMap(keccak256("eventsHub"))); @@ -271,7 +358,8 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I return _eventsHub; } - function _sellVoucher(uint256 claimAmount, uint256 maximumSharesToBurn) private returns(uint256, uint256) { + // note + function _sellVoucher(uint256 claimAmount, uint256 maximumSharesToBurn, bool legacy) private returns (uint256, uint256) { // first get how much staked in total and compare to target unstake amount (uint256 totalStaked, uint256 rate) = getTotalStake(msg.sender); require(totalStaked != 0 && totalStaked >= claimAmount, "Too much requested"); @@ -281,7 +369,7 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I uint256 shares = claimAmount.mul(precision).div(rate); require(shares <= maximumSharesToBurn, "too much slippage"); - _withdrawAndTransferReward(msg.sender); + _withdrawAndTransferReward(msg.sender, legacy); _burn(msg.sender, shares); stakeManager.updateValidatorState(validatorId, -int256(claimAmount)); @@ -294,18 +382,19 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I return (shares, _withdrawPoolShare); } - function _unstakeClaimTokens(DelegatorUnbond memory unbond) private returns(uint256) { + // @note _unstakeClaimTokens + function _unstakeClaimTokens(DelegatorUnbond memory unbond, bool legacy) private returns (uint256) { uint256 shares = unbond.shares; - require( - unbond.withdrawEpoch.add(stakeManager.withdrawalDelay()) <= stakeManager.epoch() && shares > 0, - "Incomplete withdrawal period" - ); + require(unbond.withdrawEpoch.add(stakeManager.withdrawalDelay()) <= stakeManager.epoch() && shares > 0, "Incomplete withdrawal period"); uint256 _amount = withdrawExchangeRate().mul(shares).div(_getRatePrecision()); withdrawShares = withdrawShares.sub(shares); withdrawPool = withdrawPool.sub(_amount); - require(stakeManager.transferFunds(validatorId, _amount, msg.sender), "Insufficent rewards"); + require( + legacy ? stakeManager.transferFundsLegacy(validatorId, _amount, msg.sender) : stakeManager.transferFunds(validatorId, _amount, msg.sender), + "Insufficent rewards" + ); return _amount; } @@ -323,7 +412,7 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I uint256 _rewardPerShare = rewardPerShare; if (accumulatedReward != 0) { uint256 totalShares = totalSupply(); - + if (totalShares != 0) { _rewardPerShare = _rewardPerShare.add(accumulatedReward.mul(REWARD_PRECISION).div(totalShares)); } @@ -348,30 +437,28 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I } function _withdrawReward(address user) private returns (uint256) { - uint256 _rewardPerShare = _calculateRewardPerShareWithRewards( - stakeManager.withdrawDelegatorsReward(validatorId) - ); + uint256 _rewardPerShare = _calculateRewardPerShareWithRewards(stakeManager.withdrawDelegatorsReward(validatorId)); uint256 liquidRewards = _calculateReward(user, _rewardPerShare); - + rewardPerShare = _rewardPerShare; initalRewardPerShare[user] = _rewardPerShare; return liquidRewards; } - function _withdrawAndTransferReward(address user) private returns (uint256) { + // @note _withdrawAndTransferReward + function _withdrawAndTransferReward(address user, bool legacy) private returns (uint256) { uint256 liquidRewards = _withdrawReward(user); if (liquidRewards != 0) { - require(stakeManager.transferFunds(validatorId, liquidRewards, user), "Insufficent rewards"); + require( + legacy ? stakeManager.transferFundsLegacy(validatorId, liquidRewards, user) : stakeManager.transferFunds(validatorId, liquidRewards, user), + "Insufficent rewards" + ); stakingLogger.logDelegatorClaimRewards(validatorId, user, liquidRewards); } return liquidRewards; } - function _buyShares( - uint256 _amount, - uint256 _minSharesToMint, - address user - ) private onlyWhenUnlocked returns (uint256) { + function _buyShares(uint256 _amount, uint256 _minSharesToMint, address user) private onlyWhenUnlocked returns (uint256) { require(delegation, "Delegation is disabled"); uint256 rate = exchangeRate(); @@ -395,15 +482,12 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I return _amount; } - function _transfer( - address from, - address to, - uint256 value - ) internal { - // get rewards for recipient - _withdrawAndTransferReward(to); + // @note _transfer + function _transfer(address from, address to, uint256 value, bool legacy) internal { + // get rewards for recipient + _withdrawAndTransferReward(to, legacy); // convert rewards to shares - _withdrawAndTransferReward(from); + _withdrawAndTransferReward(from, legacy); // move shares to recipient super._transfer(from, to, value); _getOrCacheEventsHub().logSharesTransfer(validatorId, from, to, value); From 344af8918949eb6e8c1c29dad65d9b4ff193fe0b Mon Sep 17 00:00:00 2001 From: Zero Ekkusu <94782988+ZeroEkkusu@users.noreply.github.com> Date: Thu, 11 Apr 2024 10:03:41 +0200 Subject: [PATCH 03/92] fix: remove `topUpForFee` and `claimFee` legacy --- contracts/staking/stakeManager/StakeManager.sol | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 5f0ed069..90d4d851 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -313,21 +313,11 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele _transferAndTopUp(user, msg.sender, heimdallFee, 0, false); } - // @note - function topUpForFeeLegacy(address user, uint256 heimdallFee) public onlyWhenUnlocked { - _transferAndTopUp(user, msg.sender, heimdallFee, 0, true); - } - // @note claimFee function claimFee(uint256 accumFeeAmount, uint256 index, bytes memory proof) public { _claimFee(accumFeeAmount, index, proof, false); } - // @note - function claimFeeLegacy(uint256 accumFeeAmount, uint256 index, bytes memory proof) public { - _claimFee(accumFeeAmount, index, proof, true); - } - // @note function _claimFee(uint256 accumFeeAmount, uint256 index, bytes memory proof, bool legacy) internal { //Ignoring other params because rewards' distribution is on chain From e763e1146998e56ad8bd144dd01d633a09351cc4 Mon Sep 17 00:00:00 2001 From: Zero Ekkusu <94782988+ZeroEkkusu@users.noreply.github.com> Date: Thu, 11 Apr 2024 10:10:45 +0200 Subject: [PATCH 04/92] fix: add check in `_transferToken` --- contracts/staking/stakeManager/StakeManager.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 90d4d851..3ba68b82 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -1131,10 +1131,11 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele } // @note _transferTokenFrom + // Do not use this function to transfer from self. function _transferTokenFrom(address from, address destination, uint256 amount, bool legacy) private { IERC20 token_ = _getToken(legacy); require(token_.transferFrom(from, destination, amount), "transfer from failed"); - if (legacy) _convertMaticToPol(amount); + if (legacy && destination == address(this)) _convertMaticToPol(amount); } // @note From 9ddfb103035339a0998436882e4b9b28b3fab417 Mon Sep 17 00:00:00 2001 From: Zero Ekkusu <94782988+ZeroEkkusu@users.noreply.github.com> Date: Mon, 20 May 2024 17:24:43 +0200 Subject: [PATCH 05/92] chore: add pr note --- contracts/staking/stakeManager/StakeManager.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 3ba68b82..4864c7c3 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -1075,6 +1075,7 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele return validatorId; } + // @note _unstake function _unstake(uint256 validatorId, uint256 exitEpoch, bool legacy) internal { // TODO: if validators unstake and slashed to 0, he will be forced to unstake again // must think how to handle it correctly From 0c3026af7eabbe5a507512eb4a602618a3aa8c93 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Wed, 22 May 2024 22:27:28 +0200 Subject: [PATCH 06/92] init legacytoken, migration --- contracts/common/misc/IPolygonMigration.sol | 6 ++++ .../staking/stakeManager/StakeManager.sol | 33 ++++++++++++------- .../stakeManager/StakeManagerStorage.sol | 5 +++ 3 files changed, 32 insertions(+), 12 deletions(-) create mode 100644 contracts/common/misc/IPolygonMigration.sol diff --git a/contracts/common/misc/IPolygonMigration.sol b/contracts/common/misc/IPolygonMigration.sol new file mode 100644 index 00000000..3adc62e9 --- /dev/null +++ b/contracts/common/misc/IPolygonMigration.sol @@ -0,0 +1,6 @@ +pragma solidity 0.5.17; + +interface IPolygonMigration { + function migrate(uint256 amount) external; + function unmigrate(uint256 amount) external; +} diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 4864c7c3..eecddd4c 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -22,6 +22,7 @@ import {StakeManagerStorageExtension} from "./StakeManagerStorageExtension.sol"; import {IGovernance} from "../../common/governance/IGovernance.sol"; import {Initializable} from "../../common/mixin/Initializable.sol"; import {StakeManagerExtension} from "./StakeManagerExtension.sol"; +import {IPolygonMigration} from "../../common/misc/IPolygonMigration.sol"; contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, DelegateProxyForwarder, StakeManagerStorageExtension { using SafeMath for uint256; @@ -72,7 +73,9 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele address _validatorShareFactory, address _governance, address _owner, - address _extensionCode + address _extensionCode, + address _tokenLegacy, + address _migration ) external initializer { require(isContract(_extensionCode), "auction impl incorrect"); extensionCode = _extensionCode; @@ -80,6 +83,8 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele registry = _registry; rootChain = _rootchain; token = IERC20(_token); + tokenLegacy = IERC20(_tokenLegacy); + migration = IPolygonMigration(_migration); NFTContract = StakingNFT(_NFTContract); logger = StakingInfo(_stakingLogger); validatorShareFactory = ValidatorShareFactory(_validatorShareFactory); @@ -203,6 +208,18 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele token = IERC20(_token); } + // @note + function setLegacyToken(address _token) public onlyGovernance { + require(_token != address(0x0)); + tokenLegacy = IERC20(_token); + } + + // @note + function setMigration(address _migration) public onlyGovernance { + require(_migration != address(0x0)); + migration = IPolygonMigration(_migration); + } + /** * @dev Change the number of validators required to allow a passed header root */ @@ -343,10 +360,10 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele } function confirmAuctionBid(uint256 validatorId, uint256 heimdallFee) + external /** * for new validator */ - external onlyWhenUnlocked { delegatedFwd( @@ -851,7 +868,7 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele if (fullIntervals > 0 && fullIntervals != prevBlockInterval) { if (prevBlockInterval != 0) { // give more reward for faster and less for slower checkpoint - uint256 delta = (ckpReward * checkpointRewardDelta / CHK_REWARD_PRECISION); + uint256 delta = ((ckpReward * checkpointRewardDelta) / CHK_REWARD_PRECISION); if (prevBlockInterval > fullIntervals) { // checkpoint is faster @@ -872,7 +889,7 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele // calculate reward for full intervals reward = ckpReward.mul(fullIntervals).sub( - ckpReward.mul(((fullIntervals - 1) * fullIntervals / 2).mul(_rewardDecreasePerCheckpoint)).div(CHK_REWARD_PRECISION) + ckpReward.mul((((fullIntervals - 1) * fullIntervals) / 2).mul(_rewardDecreasePerCheckpoint)).div(CHK_REWARD_PRECISION) ); // adjust block interval, in case last interval is not full blockInterval = blockInterval.sub(fullIntervals.mul(targetBlockInterval)); @@ -1191,9 +1208,6 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele // @note MATIC <=> POL CONVERSION // ------------------------------------------------------------------------ - IERC20 public tokenLegacy; // TODO Set MATIC and POL on reinitialization (setStakingToken). - IPolygonMigration migration; - // NOTE Convert all. function convertMaticToPol(uint256 amount) external onlyGovernance { _convertMaticToPol(amount); @@ -1215,8 +1229,3 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele token_ = !legacy ? token : tokenLegacy; } } - -interface IPolygonMigration { - function migrate(uint256 amount) external; - function unmigrate(uint256 amount) external; -} diff --git a/contracts/staking/stakeManager/StakeManagerStorage.sol b/contracts/staking/stakeManager/StakeManagerStorage.sol index 6b448a83..c25e6079 100644 --- a/contracts/staking/stakeManager/StakeManagerStorage.sol +++ b/contracts/staking/stakeManager/StakeManagerStorage.sol @@ -8,6 +8,7 @@ import {RootChainable} from "../../common/mixin/RootChainable.sol"; import {StakingInfo} from "../StakingInfo.sol"; import {StakingNFT} from "./StakingNFT.sol"; import {ValidatorShareFactory} from "../validatorShare/ValidatorShareFactory.sol"; +import {IPolygonMigration} from "../../common/misc/IPolygonMigration.sol"; contract StakeManagerStorage is GovernanceLockable, RootChainable { enum Status {Inactive, Active, Locked, Unstaked} @@ -93,4 +94,8 @@ contract StakeManagerStorage is GovernanceLockable, RootChainable { mapping(uint256 => uint256) public latestSignerUpdateEpoch; uint256 public totalHeimdallFee; + + // @note does this conflict with StakeManagerStorageExtension? + IERC20 public tokenLegacy; // TODO Set MATIC and POL on reinitialization (setStakingToken). + IPolygonMigration migration; } From 7e1fd77df3e8842bb919a26cb8c19233e4ec4f6f Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Sun, 26 May 2024 20:58:13 +0200 Subject: [PATCH 07/92] fix: transfer function overload --- contracts/staking/validatorShare/ValidatorShare.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/staking/validatorShare/ValidatorShare.sol b/contracts/staking/validatorShare/ValidatorShare.sol index e3902e63..5e25c348 100644 --- a/contracts/staking/validatorShare/ValidatorShare.sol +++ b/contracts/staking/validatorShare/ValidatorShare.sol @@ -483,7 +483,8 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I } // @note _transfer - function _transfer(address from, address to, uint256 value, bool legacy) internal { + function _transfer(address from, address to, uint256 value) internal { + bool legacy = false; // get rewards for recipient _withdrawAndTransferReward(to, legacy); // convert rewards to shares From 93cac415558a9970898a08d676bee01c71bbcad4 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Wed, 29 May 2024 13:04:30 +0200 Subject: [PATCH 08/92] fix: existing tests --- contracts/common/misc/IPolygonMigration.sol | 4 ++ contracts/common/misc/Migration.sol | 63 +++++++++++++++++++ test/helpers/artifacts.js | 1 + test/helpers/deployer.js | 18 +++++- .../staking/stakeManager/StakeManager.test.js | 2 + 5 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 contracts/common/misc/Migration.sol diff --git a/contracts/common/misc/IPolygonMigration.sol b/contracts/common/misc/IPolygonMigration.sol index 3adc62e9..02984c74 100644 --- a/contracts/common/misc/IPolygonMigration.sol +++ b/contracts/common/misc/IPolygonMigration.sol @@ -1,6 +1,10 @@ pragma solidity 0.5.17; interface IPolygonMigration { + event Migrated(address indexed account, uint256 amount); + event Unmigrated(address indexed account, address indexed recipient, uint256 amount); + event UnmigrationLockUpdated(bool lock); + function migrate(uint256 amount) external; function unmigrate(uint256 amount) external; } diff --git a/contracts/common/misc/Migration.sol b/contracts/common/misc/Migration.sol new file mode 100644 index 00000000..41d8e348 --- /dev/null +++ b/contracts/common/misc/Migration.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.5.17; + +import {IERC20} from "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol"; +import {IPolygonMigration} from "./IPolygonMigration.sol"; + +/// @title Polygon Migration +/// @author Polygon Labs (@DhairyaSethi, @gretzke, @qedk) +/// @notice This is the migration contract for Matic <-> Polygon ERC20 token on Ethereum L1 +/// @dev The contract allows for a 1-to-1 conversion from $MATIC into $POL and vice-versa +contract PolygonMigration is IPolygonMigration { + using SafeERC20 for IERC20; + + IERC20 public legacy; + IERC20 public staking; + address owner; + + bool public unmigrationLocked; + + modifier onlyUnmigrationUnlocked() { + require(unmigrationLocked, "UnmigrationLocked"); + _; + } + + modifier onlyOwner() { + require(unmigrationLocked, "UnmigrationLocked"); + _; + } + + constructor(address _legacy, address _staking) public { + staking = IERC20(_staking); + legacy = IERC20(_legacy); + owner = msg.sender; + unmigrationLocked = false; + } + + function migrate(uint256 amount) external { + emit Migrated(msg.sender, amount); + + legacy.safeTransferFrom(msg.sender, address(this), amount); + staking.safeTransfer(msg.sender, amount); + } + + function unmigrate(uint256 amount) external onlyUnmigrationUnlocked { + emit Unmigrated(msg.sender, msg.sender, amount); + + staking.safeTransferFrom(msg.sender, address(this), amount); + legacy.safeTransfer(msg.sender, amount); + } + + function unmigrateTo(address recipient, uint256 amount) external onlyUnmigrationUnlocked { + emit Unmigrated(msg.sender, recipient, amount); + + staking.safeTransferFrom(msg.sender, address(this), amount); + legacy.safeTransfer(recipient, amount); + } + + function updateUnmigrationLock(bool unmigrationLocked_) external onlyOwner { + emit UnmigrationLockUpdated(unmigrationLocked_); + unmigrationLocked = unmigrationLocked_; + } +} \ No newline at end of file diff --git a/test/helpers/artifacts.js b/test/helpers/artifacts.js index 067bc4f9..a6f6222f 100644 --- a/test/helpers/artifacts.js +++ b/test/helpers/artifacts.js @@ -49,6 +49,7 @@ export const ExitNFT = await ethers.getContractFactory('ExitNFT') export const GnosisSafeProxy = await ethers.getContractFactory('GnosisSafeProxy') export const GnosisSafe = await ethers.getContractFactory('GnosisSafe') export const PolygonMigrationTest = await ethers.getContractFactory('PolygonMigrationTest') +export const Migration = await ethers.getContractFactory('PolygonMigration') // child chain const borProvider = new ethers.providers.JsonRpcProvider( diff --git a/test/helpers/deployer.js b/test/helpers/deployer.js index 62691d3b..961fcfaa 100644 --- a/test/helpers/deployer.js +++ b/test/helpers/deployer.js @@ -24,6 +24,9 @@ class Deployer { this.eventsHub = await this.deployEventsHub(this.registry.address) this.validatorShareFactory = await contractFactories.ValidatorShareFactory.deploy() this.stakeToken = await contractFactories.TestToken.deploy('Stake Token', 'ST') + this.legacyToken = await contractFactories.TestToken.deploy('Legacy Token', 'LT') + this.migration = await contractFactories.Migration.deploy(this.stakeToken.address, this.legacyToken.address) + this.stakingInfo = await contractFactories.StakingInfo.deploy(this.registry.address) this.slashingManager = await contractFactories.SlashingManager.deploy( this.registry.address, @@ -47,7 +50,9 @@ class Deployer { this.validatorShareFactory.address, this.governance.address, owner, - auctionImpl.address + auctionImpl.address, + this.legacyToken.address, + this.migration.address ]) ) @@ -93,6 +98,9 @@ class Deployer { this.rootChain = await this.deployRootChain() this.stakingInfo = await contractFactories.StakingInfo.deploy(this.registry.address) this.stakeToken = await contractFactories.TestToken.deploy('Stake Token', 'STAKE') + this.legacyToken = await contractFactories.TestToken.deploy('Legacy Token', 'LT') + this.migration = await contractFactories.Migration.deploy(this.stakeToken.address, this.legacyToken.address) + this.stakingNFT = await contractFactories.StakingNFT.deploy('Matic Validator', 'MV') let stakeManager = await contractFactories.StakeManagerTestable.deploy() @@ -110,7 +118,9 @@ class Deployer { this.validatorShareFactory.address, this.governance.address, wallets[0].getAddressString(), - auctionImpl.address + auctionImpl.address, + this.legacyToken.address, + this.migration.address ]) ) @@ -136,7 +146,9 @@ class Deployer { governance: this.governance, stakingNFT: this.stakingNFT, stakeManagerProxy: proxy, - stakeManagerImpl: stakeManager + stakeManagerImpl: stakeManager, + legacyToken: this.legacyToken, + migration: this.migration } return _contracts } diff --git a/test/units/staking/stakeManager/StakeManager.test.js b/test/units/staking/stakeManager/StakeManager.test.js index 5244a648..99d187dc 100644 --- a/test/units/staking/stakeManager/StakeManager.test.js +++ b/test/units/staking/stakeManager/StakeManager.test.js @@ -90,6 +90,8 @@ describe('StakeManager', async function (accounts) { ZeroAddr, ZeroAddr, ZeroAddr, + ZeroAddr, + ZeroAddr, ZeroAddr ), 'already inited' From 9c1df0c9e9f8aeec63b706e2ec42fd23300ceb43 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Wed, 29 May 2024 15:39:18 +0200 Subject: [PATCH 09/92] fix: revert formating in sol files --- .../staking/stakeManager/IStakeManager.sol | 43 ++- .../staking/stakeManager/StakeManager.sol | 320 +++++++++++++----- .../staking/validatorShare/ValidatorShare.sol | 66 ++-- 3 files changed, 308 insertions(+), 121 deletions(-) diff --git a/contracts/staking/stakeManager/IStakeManager.sol b/contracts/staking/stakeManager/IStakeManager.sol index c4876bdd..8e4e95bf 100644 --- a/contracts/staking/stakeManager/IStakeManager.sol +++ b/contracts/staking/stakeManager/IStakeManager.sol @@ -2,23 +2,46 @@ pragma solidity 0.5.17; contract IStakeManager { // validator replacement - function startAuction(uint256 validatorId, uint256 amount, bool acceptDelegation, bytes calldata signerPubkey) external; + function startAuction( + uint256 validatorId, + uint256 amount, + bool acceptDelegation, + bytes calldata signerPubkey + ) external; function confirmAuctionBid(uint256 validatorId, uint256 heimdallFee) external; - function transferFunds(uint256 validatorId, uint256 amount, address delegator) external returns (bool); + function transferFunds( + uint256 validatorId, + uint256 amount, + address delegator + ) external returns (bool); - function delegationDeposit(uint256 validatorId, uint256 amount, address delegator) external returns (bool); + function delegationDeposit( + uint256 validatorId, + uint256 amount, + address delegator + ) external returns (bool); function unstake(uint256 validatorId) external; function totalStakedFor(address addr) external view returns (uint256); - function stakeFor(address user, uint256 amount, uint256 heimdallFee, bool acceptDelegation, bytes memory signerPubkey) public; + function stakeFor( + address user, + uint256 amount, + uint256 heimdallFee, + bool acceptDelegation, + bytes memory signerPubkey + ) public; - function checkSignatures(uint256 blockInterval, bytes32 voteHash, bytes32 stateRoot, address proposer, uint256[3][] calldata sigs) - external - returns (uint256); + function checkSignatures( + uint256 blockInterval, + bytes32 voteHash, + bytes32 stateRoot, + address proposer, + uint[3][] calldata sigs + ) external returns (uint256); function updateValidatorState(uint256 validatorId, int256 amount) public; @@ -34,13 +57,13 @@ contract IStakeManager { function withdrawalDelay() public view returns (uint256); - function delegatedAmount(uint256 validatorId) public view returns (uint256); + function delegatedAmount(uint256 validatorId) public view returns(uint256); function decreaseValidatorDelegatedAmount(uint256 validatorId, uint256 amount) public; - function withdrawDelegatorsReward(uint256 validatorId) public returns (uint256); + function withdrawDelegatorsReward(uint256 validatorId) public returns(uint256); - function delegatorsReward(uint256 validatorId) public view returns (uint256); + function delegatorsReward(uint256 validatorId) public view returns(uint256); function dethroneAndStake( address auctionUser, diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index eecddd4c..9efb8ad8 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -24,7 +24,13 @@ import {Initializable} from "../../common/mixin/Initializable.sol"; import {StakeManagerExtension} from "./StakeManagerExtension.sol"; import {IPolygonMigration} from "../../common/misc/IPolygonMigration.sol"; -contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, DelegateProxyForwarder, StakeManagerStorageExtension { +contract StakeManager is + StakeManagerStorage, + Initializable, + IStakeManager, + DelegateProxyForwarder, + StakeManagerStorageExtension +{ using SafeMath for uint256; using Merkle for bytes32; using RLPReader for bytes; @@ -90,18 +96,18 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele validatorShareFactory = ValidatorShareFactory(_validatorShareFactory); _transferOwnership(_owner); - WITHDRAWAL_DELAY = (2 ** 13); // unit: epoch + WITHDRAWAL_DELAY = (2**13); // unit: epoch currentEpoch = 1; dynasty = 886; // unit: epoch 50 days - CHECKPOINT_REWARD = 20_188 * (10 ** 18); // update via governance - minDeposit = (10 ** 18); // in ERC20 token - minHeimdallFee = (10 ** 18); // in ERC20 token + CHECKPOINT_REWARD = 20188 * (10**18); // update via governance + minDeposit = (10**18); // in ERC20 token + minHeimdallFee = (10**18); // in ERC20 token checkPointBlockInterval = 1024; signerUpdateLimit = 100; validatorThreshold = 7; //128 NFTCounter = 1; - auctionPeriod = (2 ** 13) / 4; // 1 week in epochs + auctionPeriod = (2**13) / 4; // 1 week in epochs proposerBonus = 10; // 10 % of total rewards delegationEnabled = true; } @@ -116,14 +122,15 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele } /** - * Public View Methods + Public View Methods */ + function getRegistry() public view returns (address) { return registry; } /** - * @dev Owner of validator slot NFT + @dev Owner of validator slot NFT */ function ownerOf(uint256 tokenId) public view returns (address) { return NFTContract.ownerOf(tokenId); @@ -160,7 +167,7 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele function validatorReward(uint256 validatorId) public view returns (uint256) { uint256 _validatorReward; if (validators[validatorId].deactivationEpoch == 0) { - (_validatorReward,) = _evaluateValidatorAndDelegationReward(validatorId); + (_validatorReward, ) = _evaluateValidatorAndDelegationReward(validatorId); } return validators[validatorId].reward.add(_validatorReward).sub(INITIALIZED_AMOUNT); } @@ -178,12 +185,19 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele } function isValidator(uint256 validatorId) public view returns (bool) { - return _isValidator(validators[validatorId].status, validators[validatorId].amount, validators[validatorId].deactivationEpoch, currentEpoch); + return + _isValidator( + validators[validatorId].status, + validators[validatorId].amount, + validators[validatorId].deactivationEpoch, + currentEpoch + ); } /** - * Governance Methods + Governance Methods */ + function setDelegationEnabled(bool enabled) public onlyGovernance { delegationEnabled = enabled; } @@ -240,10 +254,11 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele CHECKPOINT_REWARD = newReward; } - function updateCheckpointRewardParams(uint256 _rewardDecreasePerCheckpoint, uint256 _maxRewardedCheckpoints, uint256 _checkpointRewardDelta) - public - onlyGovernance - { + function updateCheckpointRewardParams( + uint256 _rewardDecreasePerCheckpoint, + uint256 _maxRewardedCheckpoints, + uint256 _checkpointRewardDelta + ) public onlyGovernance { delegatedFwd( extensionCode, abi.encodeWithSelector( @@ -258,7 +273,14 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele // New implementation upgrade function migrateValidatorsData(uint256 validatorIdFrom, uint256 validatorIdTo) public onlyOwner { - delegatedFwd(extensionCode, abi.encodeWithSelector(StakeManagerExtension(extensionCode).migrateValidatorsData.selector, validatorIdFrom, validatorIdTo)); + delegatedFwd( + extensionCode, + abi.encodeWithSelector( + StakeManagerExtension(extensionCode).migrateValidatorsData.selector, + validatorIdFrom, + validatorIdTo + ) + ); } function insertSigners(address[] memory _signers) public onlyOwner { @@ -266,7 +288,7 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele } /** - * @dev Users must exit before this update or all funds may get lost + @dev Users must exit before this update or all funds may get lost */ function updateValidatorContractAddress(uint256 validatorId, address newContractAddress) public onlyGovernance { require(IValidatorShare(newContractAddress).owner() == address(this)); @@ -302,7 +324,12 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele minHeimdallFee = _minHeimdallFee; } - function drainValidatorShares(uint256 validatorId, address tokenAddr, address payable destination, uint256 amount) external onlyGovernance { + function drainValidatorShares( + uint256 validatorId, + address tokenAddr, + address payable destination, + uint256 amount + ) external onlyGovernance { address contractAddr = validators[validatorId].contractAddress; require(contractAddr != address(0x0)); IValidatorShare(contractAddr).drain(tokenAddr, destination, amount); @@ -313,7 +340,12 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele _transferToken(destination, amount, false); } - function reinitialize(address _NFTContract, address _stakingLogger, address _validatorShareFactory, address _extensionCode) external onlyGovernance { + function reinitialize( + address _NFTContract, + address _stakingLogger, + address _validatorShareFactory, + address _extensionCode + ) external onlyGovernance { require(isContract(_extensionCode)); eventsHub = address(0x0); extensionCode = _extensionCode; @@ -323,7 +355,7 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele } /** - * Public Methods + Public Methods */ // @note topUpForFee function topUpForFee(address user, uint256 heimdallFee) public onlyWhenUnlocked { @@ -352,22 +384,36 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele return validators[NFTContract.tokenOfOwnerByIndex(user, 0)].amount; } - function startAuction(uint256 validatorId, uint256 amount, bool _acceptDelegation, bytes calldata _signerPubkey) external onlyWhenUnlocked { + function startAuction( + uint256 validatorId, + uint256 amount, + bool _acceptDelegation, + bytes calldata _signerPubkey + ) external onlyWhenUnlocked { delegatedFwd( extensionCode, - abi.encodeWithSelector(StakeManagerExtension(extensionCode).startAuction.selector, validatorId, amount, _acceptDelegation, _signerPubkey) + abi.encodeWithSelector( + StakeManagerExtension(extensionCode).startAuction.selector, + validatorId, + amount, + _acceptDelegation, + _signerPubkey + ) ); } - function confirmAuctionBid(uint256 validatorId, uint256 heimdallFee) - external - /** - * for new validator - */ - onlyWhenUnlocked - { + function confirmAuctionBid( + uint256 validatorId, + uint256 heimdallFee /** for new validator */ + ) external onlyWhenUnlocked { delegatedFwd( - extensionCode, abi.encodeWithSelector(StakeManagerExtension(extensionCode).confirmAuctionBid.selector, validatorId, heimdallFee, address(this)) + extensionCode, + abi.encodeWithSelector( + StakeManagerExtension(extensionCode).confirmAuctionBid.selector, + validatorId, + heimdallFee, + address(this) + ) ); } @@ -430,8 +476,9 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele Status status = validators[validatorId].status; require( - validators[validatorId].activationEpoch > 0 && validators[validatorId].deactivationEpoch == 0 - && (status == Status.Active || status == Status.Locked) + validators[validatorId].activationEpoch > 0 && + validators[validatorId].deactivationEpoch == 0 && + (status == Status.Active || status == Status.Locked) ); uint256 exitEpoch = currentEpoch.add(1); // notice period @@ -506,7 +553,11 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele function _unstakeClaim(uint256 validatorId, bool legacy) internal { uint256 deactivationEpoch = validators[validatorId].deactivationEpoch; // can only claim stake back after WITHDRAWAL_DELAY - require(deactivationEpoch > 0 && deactivationEpoch.add(WITHDRAWAL_DELAY) <= currentEpoch && validators[validatorId].status != Status.Unstaked); + require( + deactivationEpoch > 0 && + deactivationEpoch.add(WITHDRAWAL_DELAY) <= currentEpoch && + validators[validatorId].status != Status.Unstaked + ); uint256 amount = validators[validatorId].amount; uint256 newTotalStaked = totalStaked.sub(amount); @@ -579,7 +630,11 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele _liquidateRewards(validatorId, msg.sender, legacy); } - function migrateDelegation(uint256 fromValidatorId, uint256 toValidatorId, uint256 amount) public { + function migrateDelegation( + uint256 fromValidatorId, + uint256 toValidatorId, + uint256 amount + ) public { // allow to move to any non-foundation node require(toValidatorId > 7, "Invalid migration"); IValidatorShare(validators[fromValidatorId].contractAddress).migrateOut(msg.sender, amount); @@ -594,13 +649,12 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele uint256 deactivationEpoch = validators[validatorId].deactivationEpoch; - if (deactivationEpoch == 0) { - // modify timeline only if validator didn't unstake + if (deactivationEpoch == 0) { // modify timeline only if validator didn't unstake updateTimeline(amount, 0, 0); - } else if (deactivationEpoch > currentEpoch) { - // validator just unstaked, need to wait till next checkpoint + } else if (deactivationEpoch > currentEpoch) { // validator just unstaked, need to wait till next checkpoint revert("unstaking"); } + if (amount >= 0) { increaseValidatorDelegatedAmount(validatorId, uint256(amount)); @@ -625,8 +679,8 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele address currentSigner = validators[validatorId].signer; // update signer event logger.logSignerChange(validatorId, currentSigner, signer, signerPubkey); - - if (validators[validatorId].deactivationEpoch == 0) { + + if (validators[validatorId].deactivationEpoch == 0) { // didn't unstake, swap signer in the list _removeSigner(currentSigner); _insertSigner(signer); @@ -640,11 +694,13 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele latestSignerUpdateEpoch[validatorId] = _currentEpoch; } - function checkSignatures(uint256 blockInterval, bytes32 voteHash, bytes32 stateRoot, address proposer, uint256[3][] calldata sigs) - external - onlyRootChain - returns (uint256) - { + function checkSignatures( + uint256 blockInterval, + bytes32 voteHash, + bytes32 stateRoot, + address proposer, + uint256[3][] calldata sigs + ) external onlyRootChain returns (uint256) { uint256 _currentEpoch = currentEpoch; uint256 signedStakePower; address lastAdd; @@ -701,22 +757,30 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele // find the rest of validators without signature unsignedCtx = _fillUnsignedValidators(unsignedCtx, address(0)); - return _increaseRewardAndAssertConsensus( - blockInterval, - proposer, - signedStakePower, - stateRoot, - unsignedCtx.unsignedValidators, - unsignedCtx.unsignedValidatorIndex, - unstakeCtx.deactivatedValidators, - unstakeCtx.validatorIndex - ); + return + _increaseRewardAndAssertConsensus( + blockInterval, + proposer, + signedStakePower, + stateRoot, + unsignedCtx.unsignedValidators, + unsignedCtx.unsignedValidatorIndex, + unstakeCtx.deactivatedValidators, + unstakeCtx.validatorIndex + ); } function updateCommissionRate(uint256 validatorId, uint256 newCommissionRate) external onlyStaker(validatorId) { _updateRewards(validatorId); - delegatedFwd(extensionCode, abi.encodeWithSelector(StakeManagerExtension(extensionCode).updateCommissionRate.selector, validatorId, newCommissionRate)); + delegatedFwd( + extensionCode, + abi.encodeWithSelector( + StakeManagerExtension(extensionCode).updateCommissionRate.selector, + validatorId, + newCommissionRate + ) + ); } function withdrawDelegatorsReward(uint256 validatorId) public onlyDelegation(validatorId) returns (uint256) { @@ -749,7 +813,11 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele address delegationContract = validators[validatorId].contractAddress; if (delegationContract != address(0x0)) { uint256 delSlashedAmount = - IValidatorShare(delegationContract).slash(validators[validatorId].amount, validators[validatorId].delegatedAmount, _amount); + IValidatorShare(delegationContract).slash( + validators[validatorId].amount, + validators[validatorId].delegatedAmount, + _amount + ); _amount = _amount.sub(delSlashedAmount); } @@ -794,7 +862,11 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele logger.logUnjailed(validatorId, signer); } - function updateTimeline(int256 amount, int256 stakerCount, uint256 targetEpoch) internal { + function updateTimeline( + int256 amount, + int256 stakerCount, + uint256 targetEpoch + ) internal { if (targetEpoch == 0) { // update total stake and validator count if (amount > 0) { @@ -817,7 +889,12 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele function updateValidatorDelegation(bool delegation) external { uint256 validatorId = signerToValidator[msg.sender]; require( - _isValidator(validators[validatorId].status, validators[validatorId].amount, validators[validatorId].deactivationEpoch, currentEpoch), + _isValidator( + validators[validatorId].status, + validators[validatorId].amount, + validators[validatorId].deactivationEpoch, + currentEpoch + ), "not validator" ); @@ -828,8 +905,9 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele } /** - * Private Methods + Private Methods */ + function _getAndAssertSigner(bytes memory pub) private view returns (address) { require(pub.length == 64, "not pub"); address signer = address(uint160(uint256(keccak256(pub)))); @@ -837,11 +915,20 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele return signer; } - function _isValidator(Status status, uint256 amount, uint256 deactivationEpoch, uint256 _currentEpoch) private pure returns (bool) { + function _isValidator( + Status status, + uint256 amount, + uint256 deactivationEpoch, + uint256 _currentEpoch + ) private pure returns (bool) { return (amount > 0 && (deactivationEpoch == 0 || deactivationEpoch > _currentEpoch) && status == Status.Active); } - function _fillUnsignedValidators(UnsignedValidatorsContext memory context, address signer) private view returns (UnsignedValidatorsContext memory) { + function _fillUnsignedValidators(UnsignedValidatorsContext memory context, address signer) + private + view + returns(UnsignedValidatorsContext memory) + { while (context.validatorIndex < context.totalValidators && context.validators[context.validatorIndex] != signer) { context.unsignedValidators[context.unsignedValidatorIndex] = signerToValidator[context.validators[context.validatorIndex]]; context.unsignedValidatorIndex++; @@ -852,7 +939,11 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele return context; } - function _calculateCheckpointReward(uint256 blockInterval, uint256 signedStakePower, uint256 currentTotalStake) internal returns (uint256) { + function _calculateCheckpointReward( + uint256 blockInterval, + uint256 signedStakePower, + uint256 currentTotalStake + ) internal returns (uint256) { // checkpoint rewards are based on BlockInterval multiplied on `CHECKPOINT_REWARD` // for bigger checkpoints reward is reduced by rewardDecreasePerCheckpoint for each subsequent interval @@ -868,8 +959,8 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele if (fullIntervals > 0 && fullIntervals != prevBlockInterval) { if (prevBlockInterval != 0) { // give more reward for faster and less for slower checkpoint - uint256 delta = ((ckpReward * checkpointRewardDelta) / CHK_REWARD_PRECISION); - + uint256 delta = (ckpReward * checkpointRewardDelta / CHK_REWARD_PRECISION); + if (prevBlockInterval > fullIntervals) { // checkpoint is faster ckpReward += delta; @@ -877,7 +968,7 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele ckpReward -= delta; } } - + prevBlockInterval = fullIntervals; } @@ -888,9 +979,7 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele uint256 _rewardDecreasePerCheckpoint = rewardDecreasePerCheckpoint; // calculate reward for full intervals - reward = ckpReward.mul(fullIntervals).sub( - ckpReward.mul((((fullIntervals - 1) * fullIntervals) / 2).mul(_rewardDecreasePerCheckpoint)).div(CHK_REWARD_PRECISION) - ); + reward = ckpReward.mul(fullIntervals).sub(ckpReward.mul(((fullIntervals - 1) * fullIntervals / 2).mul(_rewardDecreasePerCheckpoint)).div(CHK_REWARD_PRECISION)); // adjust block interval, in case last interval is not full blockInterval = blockInterval.sub(fullIntervals.mul(targetBlockInterval)); // adjust checkpoint reward by the amount it suppose to decrease @@ -927,7 +1016,8 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele // update stateMerkleTree root for accounts balance on heimdall chain accountStateRoot = stateRoot; - uint256 newRewardPerStake = rewardPerStake.add(reward.sub(_proposerBonus).mul(REWARD_PRECISION).div(signedStakePower)); + uint256 newRewardPerStake = + rewardPerStake.add(reward.sub(_proposerBonus).mul(REWARD_PRECISION).div(signedStakePower)); // evaluate rewards for validator who did't sign and set latest reward per stake to new value to avoid them from getting new rewards. _updateValidatorsRewards(unsignedValidators, totalUnsignedValidators, newRewardPerStake); @@ -942,14 +1032,22 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele return reward; } - function _updateValidatorsRewards(uint256[] memory unsignedValidators, uint256 totalUnsignedValidators, uint256 newRewardPerStake) private { + function _updateValidatorsRewards( + uint256[] memory unsignedValidators, + uint256 totalUnsignedValidators, + uint256 newRewardPerStake + ) private { uint256 currentRewardPerStake = rewardPerStake; for (uint256 i = 0; i < totalUnsignedValidators; ++i) { _updateRewardsAndCommit(unsignedValidators[i], currentRewardPerStake, newRewardPerStake); } } - function _updateRewardsAndCommit(uint256 validatorId, uint256 currentRewardPerStake, uint256 newRewardPerStake) private { + function _updateRewardsAndCommit( + uint256 validatorId, + uint256 currentRewardPerStake, + uint256 newRewardPerStake + ) private { uint256 deactivationEpoch = validators[validatorId].deactivationEpoch; if (deactivationEpoch != 0 && currentEpoch >= deactivationEpoch) { return; @@ -967,10 +1065,23 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele validatorId, validatorsStake, delegatedAmount, - _getEligibleValidatorReward(validatorId, combinedStakePower, currentRewardPerStake, initialRewardPerStake) + _getEligibleValidatorReward( + validatorId, + combinedStakePower, + currentRewardPerStake, + initialRewardPerStake + ) ); } else { - _increaseValidatorReward(validatorId, _getEligibleValidatorReward(validatorId, validatorsStake, currentRewardPerStake, initialRewardPerStake)); + _increaseValidatorReward( + validatorId, + _getEligibleValidatorReward( + validatorId, + validatorsStake, + currentRewardPerStake, + initialRewardPerStake + ) + ); } } @@ -983,11 +1094,12 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele _updateRewardsAndCommit(validatorId, rewardPerStake, rewardPerStake); } - function _getEligibleValidatorReward(uint256 validatorId, uint256 validatorStakePower, uint256 currentRewardPerStake, uint256 initialRewardPerStake) - private - pure - returns (uint256) - { + function _getEligibleValidatorReward( + uint256 validatorId, + uint256 validatorStakePower, + uint256 currentRewardPerStake, + uint256 initialRewardPerStake + ) private pure returns (uint256) { uint256 eligibleReward = currentRewardPerStake - initialRewardPerStake; return eligibleReward.mul(validatorStakePower).div(REWARD_PRECISION); } @@ -998,9 +1110,15 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele } } - function _increaseValidatorRewardWithDelegation(uint256 validatorId, uint256 validatorsStake, uint256 delegatedAmount, uint256 reward) private { + function _increaseValidatorRewardWithDelegation( + uint256 validatorId, + uint256 validatorsStake, + uint256 delegatedAmount, + uint256 reward + ) private { uint256 combinedStakePower = delegatedAmount.add(validatorsStake); - (uint256 validatorReward, uint256 delegatorsReward) = _getValidatorAndDelegationReward(validatorId, validatorsStake, reward, combinedStakePower); + (uint256 validatorReward, uint256 delegatorsReward) = + _getValidatorAndDelegationReward(validatorId, validatorsStake, reward, combinedStakePower); if (delegatorsReward > 0) { validators[validatorId].delegatorsReward = validators[validatorId].delegatorsReward.add(delegatorsReward); @@ -1011,11 +1129,12 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele } } - function _getValidatorAndDelegationReward(uint256 validatorId, uint256 validatorsStake, uint256 reward, uint256 combinedStakePower) - internal - view - returns (uint256, uint256) - { + function _getValidatorAndDelegationReward( + uint256 validatorId, + uint256 validatorsStake, + uint256 reward, + uint256 combinedStakePower + ) internal view returns (uint256, uint256) { if (combinedStakePower == 0) { return (0, 0); } @@ -1025,18 +1144,30 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele // add validator commission from delegation reward uint256 commissionRate = validators[validatorId].commissionRate; if (commissionRate > 0) { - validatorReward = validatorReward.add(reward.sub(validatorReward).mul(commissionRate).div(MAX_COMMISION_RATE)); + validatorReward = validatorReward.add( + reward.sub(validatorReward).mul(commissionRate).div(MAX_COMMISION_RATE) + ); } uint256 delegatorsReward = reward.sub(validatorReward); return (validatorReward, delegatorsReward); } - function _evaluateValidatorAndDelegationReward(uint256 validatorId) private view returns (uint256 validatorReward, uint256 delegatorsReward) { + function _evaluateValidatorAndDelegationReward(uint256 validatorId) + private + view + returns (uint256 validatorReward, uint256 delegatorsReward) + { uint256 validatorsStake = validators[validatorId].amount; uint256 combinedStakePower = validatorsStake.add(validators[validatorId].delegatedAmount); uint256 eligibleReward = rewardPerStake - validators[validatorId].initialRewardPerStake; - return _getValidatorAndDelegationReward(validatorId, validatorsStake, eligibleReward.mul(combinedStakePower).div(REWARD_PRECISION), combinedStakePower); + return + _getValidatorAndDelegationReward( + validatorId, + validatorsStake, + eligibleReward.mul(combinedStakePower).div(REWARD_PRECISION), + combinedStakePower + ); } function _jail(uint256 validatorId, uint256 jailCheckpoints) internal returns (uint256) { @@ -1052,7 +1183,12 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele return validators[validatorId].amount.add(validators[validatorId].delegatedAmount); } - function _stakeFor(address user, uint256 amount, bool acceptDelegation, bytes memory signerPubkey) internal returns (uint256) { + function _stakeFor( + address user, + uint256 amount, + bool acceptDelegation, + bytes memory signerPubkey + ) internal returns (uint256) { address signer = _getAndAssertSigner(signerPubkey); uint256 _currentEpoch = currentEpoch; uint256 validatorId = NFTCounter; @@ -1068,7 +1204,9 @@ contract StakeManager is StakeManagerStorage, Initializable, IStakeManager, Dele deactivationEpoch: 0, jailTime: 0, signer: signer, - contractAddress: acceptDelegation ? validatorShareFactory.create(validatorId, address(_logger), registry) : address(0x0), + contractAddress: acceptDelegation + ? validatorShareFactory.create(validatorId, address(_logger), registry) + : address(0x0), status: Status.Active, commissionRate: 0, lastCommissionUpdate: 0, diff --git a/contracts/staking/validatorShare/ValidatorShare.sol b/contracts/staking/validatorShare/ValidatorShare.sol index 5e25c348..b4d56f86 100644 --- a/contracts/staking/validatorShare/ValidatorShare.sol +++ b/contracts/staking/validatorShare/ValidatorShare.sol @@ -18,9 +18,9 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I uint256 constant EXCHANGE_RATE_PRECISION = 100; // maximum matic possible, even if rate will be 1 and all matic will be staken in one go, it will result in 10 ^ 58 shares - uint256 constant EXCHANGE_RATE_HIGH_PRECISION = 10 ** 29; + uint256 constant EXCHANGE_RATE_HIGH_PRECISION = 10**29; uint256 constant MAX_COMMISION_RATE = 100; - uint256 constant REWARD_PRECISION = 10 ** 25; + uint256 constant REWARD_PRECISION = 10**25; StakingInfo public stakingLogger; IStakeManager public stakeManager; @@ -49,20 +49,25 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I EventsHub public eventsHub; // onlyOwner will prevent this contract from initializing, since it's owner is going to be 0x0 address - function initialize(uint256 _validatorId, address _stakingLogger, address _stakeManager) external initializer { + function initialize( + uint256 _validatorId, + address _stakingLogger, + address _stakeManager + ) external initializer { validatorId = _validatorId; stakingLogger = StakingInfo(_stakingLogger); stakeManager = IStakeManager(_stakeManager); _transferOwnership(_stakeManager); _getOrCacheEventsHub(); - minAmount = 10 ** 18; + minAmount = 10**18; delegation = true; } /** - * Public View Methods - */ + Public View Methods + */ + function exchangeRate() public view returns (uint256) { uint256 totalShares = totalSupply(); uint256 precision = _getRatePrecision(); @@ -101,7 +106,7 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I } /** - * Public Methods + Public Methods */ // @note buyVoucher function buyVoucher(uint256 _amount, uint256 _minSharesToMint) public returns (uint256 amountToDeposit) { @@ -160,10 +165,10 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I stakingLogger.logDelegatorClaimRewards(validatorId, user, liquidReward - amountRestaked); } - (uint256 totalStaked,) = getTotalStake(user); + (uint256 totalStaked, ) = getTotalStake(user); stakingLogger.logDelegatorRestaked(validatorId, user, totalStaked); } - + return (amountRestaked, liquidReward); } @@ -270,7 +275,11 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I stakingLogger.logDelegatorUnstaked(validatorId, msg.sender, amount); } - function slash(uint256 validatorStake, uint256 delegatedAmount, uint256 totalAmountToSlash) external onlyOwner returns (uint256) { + function slash( + uint256 validatorStake, + uint256 delegatedAmount, + uint256 totalAmountToSlash + ) external onlyOwner returns (uint256) { uint256 _withdrawPool = withdrawPool; uint256 delegationAmount = delegatedAmount.add(_withdrawPool); if (delegationAmount == 0) { @@ -293,7 +302,11 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I delegation = _delegation; } - function drain(address token, address payable destination, uint256 amount) external onlyOwner { + function drain( + address token, + address payable destination, + uint256 amount + ) external onlyOwner { if (token == address(0x0)) { destination.transfer(amount); } else { @@ -302,7 +315,7 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I } /** - * New shares exit API + New shares exit API */ // @note sellVoucher_new function sellVoucher_new(uint256 claimAmount, uint256 maximumSharesToBurn) public { @@ -320,7 +333,10 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I uint256 unbondNonce = unbondNonces[msg.sender].add(1); - DelegatorUnbond memory unbond = DelegatorUnbond({shares: _withdrawPoolShare, withdrawEpoch: stakeManager.epoch()}); + DelegatorUnbond memory unbond = DelegatorUnbond({ + shares: _withdrawPoolShare, + withdrawEpoch: stakeManager.epoch() + }); unbonds_new[msg.sender][unbondNonce] = unbond; unbondNonces[msg.sender] = unbondNonce; @@ -347,9 +363,10 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I } /** - * Private Methods + Private Methods */ - function _getOrCacheEventsHub() private returns (EventsHub) { + + function _getOrCacheEventsHub() private returns(EventsHub) { EventsHub _eventsHub = eventsHub; if (_eventsHub == EventsHub(0x0)) { _eventsHub = EventsHub(Registry(stakeManager.getRegistry()).contractMap(keccak256("eventsHub"))); @@ -385,7 +402,10 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I // @note _unstakeClaimTokens function _unstakeClaimTokens(DelegatorUnbond memory unbond, bool legacy) private returns (uint256) { uint256 shares = unbond.shares; - require(unbond.withdrawEpoch.add(stakeManager.withdrawalDelay()) <= stakeManager.epoch() && shares > 0, "Incomplete withdrawal period"); + require( + unbond.withdrawEpoch.add(stakeManager.withdrawalDelay()) <= stakeManager.epoch() && shares > 0, + "Incomplete withdrawal period" + ); uint256 _amount = withdrawExchangeRate().mul(shares).div(_getRatePrecision()); withdrawShares = withdrawShares.sub(shares); @@ -412,7 +432,7 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I uint256 _rewardPerShare = rewardPerShare; if (accumulatedReward != 0) { uint256 totalShares = totalSupply(); - + if (totalShares != 0) { _rewardPerShare = _rewardPerShare.add(accumulatedReward.mul(REWARD_PRECISION).div(totalShares)); } @@ -437,9 +457,11 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I } function _withdrawReward(address user) private returns (uint256) { - uint256 _rewardPerShare = _calculateRewardPerShareWithRewards(stakeManager.withdrawDelegatorsReward(validatorId)); + uint256 _rewardPerShare = _calculateRewardPerShareWithRewards( + stakeManager.withdrawDelegatorsReward(validatorId) + ); uint256 liquidRewards = _calculateReward(user, _rewardPerShare); - + rewardPerShare = _rewardPerShare; initalRewardPerShare[user] = _rewardPerShare; return liquidRewards; @@ -458,7 +480,11 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I return liquidRewards; } - function _buyShares(uint256 _amount, uint256 _minSharesToMint, address user) private onlyWhenUnlocked returns (uint256) { + function _buyShares( + uint256 _amount, + uint256 _minSharesToMint, + address user + ) private onlyWhenUnlocked returns (uint256) { require(delegation, "Delegation is disabled"); uint256 rate = exchangeRate(); From eafb462c3b0ae5b63408dcff15b028ee07c0b606 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Wed, 29 May 2024 17:29:33 +0200 Subject: [PATCH 10/92] fix: allow stakemanager tests to run independently --- .../staking/stakeManager/StakeManager.test.js | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/test/units/staking/stakeManager/StakeManager.test.js b/test/units/staking/stakeManager/StakeManager.test.js index 99d187dc..10b278f2 100644 --- a/test/units/staking/stakeManager/StakeManager.test.js +++ b/test/units/staking/stakeManager/StakeManager.test.js @@ -64,14 +64,16 @@ function testCheckpointing( const ZeroAddr = '0x0000000000000000000000000000000000000000' -describe('StakeManager', async function (accounts) { - accounts = await ethers.getSigners() - accounts = accounts.map((account) => { +describe('StakeManager', function (accounts) { + let owner + before(async ()=>{ + accounts = await ethers.getSigners() + accounts = accounts.map((account) => { return account.address }) - - let owner = accounts[0] - + owner = accounts[0] + }) + describe('initialize', function () { describe('when called directly on implementation', function () { before(freshDeploy) @@ -944,7 +946,7 @@ describe('StakeManager', async function (accounts) { this.index = 0 } - describe('Deploying and staking with 4 validators...', async function () { + describe('Deploying and staking with 4 validators...', function () { const AliceValidatorId = 1 const firstFeeToClaim = new BN(web3.utils.toWei('25')) @@ -1711,7 +1713,7 @@ describe('StakeManager', async function (accounts) { }) } - describe('when Alice topups once and claims 2 times', async function () { + describe('when Alice topups once and claims 2 times', function () { const AliceValidatorId = 1 const totalFee = new BN(web3.utils.toWei('100')).toString() const firstFeeToClaim = new BN(web3.utils.toWei('25')) @@ -2226,7 +2228,7 @@ describe('StakeManager', async function (accounts) { }) }) - describe('auction with delegator, 3 validators initially', async function () { + describe('auction with delegator, 3 validators initially', function () { const initialStakers = [wallets[1], wallets[2]] const delegatedValidatorId = '3' const delegator = wallets[3].getChecksumAddressString() @@ -2534,7 +2536,7 @@ describe('StakeManager', async function (accounts) { }) }) - describe('when Chad delegates to Alice then migrates partialy to Bob', async function () { + describe('when Chad delegates to Alice then migrates partialy to Bob', function () { const aliceId = '2' const bobId = '8' const delegator = wallets[9].getChecksumAddressString() @@ -2549,7 +2551,7 @@ describe('StakeManager', async function (accounts) { aliceContract = await ValidatorShare.attach(aliceValidator.contractAddress) }) - describe('Chad delegates to Alice', async function () { + describe('Chad delegates to Alice', function () { it('Should delegate', async function () { this.receipt = await (await buyVoucher(aliceContract, delegationAmount, delegator)).wait() }) @@ -2584,7 +2586,7 @@ describe('StakeManager', async function (accounts) { }) }) - describe('Chad migrates delegation to Bob', async function () { + describe('Chad migrates delegation to Bob', function () { it('Should migrate', async function () { this.receipt = await (await stakeManager9.migrateDelegation(aliceId, bobId, migrationAmount)).wait() }) @@ -2692,7 +2694,7 @@ describe('StakeManager', async function (accounts) { }) }) - describe('when Chad migrates with more tokens than his delegation amount', async function () { + describe('when Chad migrates with more tokens than his delegation amount', function () { const aliceId = '2' const bobId = '8' const delegator = wallets[9].getChecksumAddressString() From 08895bc0362192e3cbe5292af90bf643b14998ef Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Fri, 7 Jun 2024 17:25:21 +0200 Subject: [PATCH 11/92] fix: test preparation --- test/helpers/deployer.js | 8 +++- test/units/staking/ValidatorShareHelper.js | 32 ++++++++++++++ test/units/staking/deployment.js | 50 ++++++++++++++++------ 3 files changed, 75 insertions(+), 15 deletions(-) diff --git a/test/helpers/deployer.js b/test/helpers/deployer.js index 961fcfaa..823f76b8 100644 --- a/test/helpers/deployer.js +++ b/test/helpers/deployer.js @@ -25,7 +25,7 @@ class Deployer { this.validatorShareFactory = await contractFactories.ValidatorShareFactory.deploy() this.stakeToken = await contractFactories.TestToken.deploy('Stake Token', 'ST') this.legacyToken = await contractFactories.TestToken.deploy('Legacy Token', 'LT') - this.migration = await contractFactories.Migration.deploy(this.stakeToken.address, this.legacyToken.address) + this.migration = await contractFactories.Migration.deploy(this.legacyToken.address, this.stakeToken.address) this.stakingInfo = await contractFactories.StakingInfo.deploy(this.registry.address) this.slashingManager = await contractFactories.SlashingManager.deploy( @@ -99,8 +99,12 @@ class Deployer { this.stakingInfo = await contractFactories.StakingInfo.deploy(this.registry.address) this.stakeToken = await contractFactories.TestToken.deploy('Stake Token', 'STAKE') this.legacyToken = await contractFactories.TestToken.deploy('Legacy Token', 'LT') - this.migration = await contractFactories.Migration.deploy(this.stakeToken.address, this.legacyToken.address) + this.migration = await contractFactories.Migration.deploy(this.legacyToken.address, this.stakeToken.address) + // Mint token into migration, so we can actually migrate + await this.stakeToken.mint(this.migration.address, web3.utils.toWei('1000000')) + await this.legacyToken.mint(this.migration.address, web3.utils.toWei('1000000')) + this.stakingNFT = await contractFactories.StakingNFT.deploy('Matic Validator', 'MV') let stakeManager = await contractFactories.StakeManagerTestable.deploy() diff --git a/test/units/staking/ValidatorShareHelper.js b/test/units/staking/ValidatorShareHelper.js index ec557c52..563f1030 100644 --- a/test/units/staking/ValidatorShareHelper.js +++ b/test/units/staking/ValidatorShareHelper.js @@ -29,3 +29,35 @@ export async function sellVoucherNew(validatorContract, delegator, minClaimAmoun return validatorContract_Delegator.sellVoucher_new(minClaimAmount.toString(), maxShares) } + +export async function buyVoucherLegacy(validatorContract, amount, delegator, minSharesToMint) { + const validatorContract_Delegator = validatorContract.connect(validatorContract.provider.getSigner(delegator)) + return validatorContract_Delegator.buyVoucherLegacy(amount.toString(), minSharesToMint || 0) +} + +export async function sellVoucherLegacy(validatorContract, delegator, minClaimAmount, maxShares) { + if (maxShares === undefined) { + maxShares = await validatorContract.balanceOf(delegator) + } + + if (minClaimAmount === undefined) { + minClaimAmount = await validatorContract.amountStaked(delegator) + } + + const validatorContract_Delegator = validatorContract.connect(validatorContract.provider.getSigner(delegator)) + + return validatorContract_Delegator.sellVoucherLegacy(minClaimAmount, maxShares) +} + +export async function sellVoucherNewLegacy(validatorContract, delegator, minClaimAmount, maxShares) { + if (maxShares === undefined) { + maxShares = await validatorContract.balanceOf(delegator) + } + + if (minClaimAmount === undefined) { + minClaimAmount = await validatorContract.amountStaked(delegator) + } + const validatorContract_Delegator = validatorContract.connect(validatorContract.provider.getSigner(delegator)) + + return validatorContract_Delegator.sellVoucher_newLegacy(minClaimAmount.toString(), maxShares) +} diff --git a/test/units/staking/deployment.js b/test/units/staking/deployment.js index aed2f4e9..44de9044 100644 --- a/test/units/staking/deployment.js +++ b/test/units/staking/deployment.js @@ -37,6 +37,7 @@ export const walletAmounts = { export async function freshDeploy() { let contracts = await deployer.deployStakeManager(wallets) this.stakeToken = contracts.stakeToken + this.legacyToken = contracts.legacyToken this.stakeManager = contracts.stakeManager this.nftContract = contracts.stakingNFT this.rootChainOwner = contracts.rootChainOwner @@ -44,6 +45,7 @@ export async function freshDeploy() { this.governance = contracts.governance this.validatorShare = deployer.validatorShare this.slashingManager = contracts.slashingManager + this.migration = contracts.migration await this.governance.update( this.stakeManager.address, @@ -55,10 +57,12 @@ export async function freshDeploy() { ) for (const walletAddr in walletAmounts) { + await this.legacyToken.mint(walletAddr, walletAmounts[walletAddr].initialBalance) await this.stakeToken.mint(walletAddr, walletAmounts[walletAddr].initialBalance) } await this.stakeToken.mint(this.stakeManager.address, web3.utils.toWei('10000000')) + await this.legacyToken.mint(this.stakeManager.address, web3.utils.toWei('20000000')) this.defaultHeimdallFee = new BN(web3.utils.toWei('1')) } @@ -70,32 +74,52 @@ export async function approveAndStake({ acceptDelegation = false, heimdallFee, noMinting = false, - signer + signer, + legacy = false }) { const fee = heimdallFee || this.defaultHeimdallFee const mintAmount = new BN(approveAmount || stakeAmount).add(new BN(fee)) + let token + if (legacy) { + token = this.legacyToken + } else { + token = this.stakeToken + } + if (noMinting) { // check if allowance covers fee - const balance = await this.stakeToken.balanceOf(wallet.getAddressString()) + const balance = await token.balanceOf(wallet.getAddressString()) if (balance.lt(mintAmount.toString())) { // mint more - await this.stakeToken.mint(wallet.getAddressString(), mintAmount.sub(balance).toString()) + await token.mint(wallet.getAddressString(), mintAmount.sub(balance).toString()) } } else { - await this.stakeToken.mint(wallet.getAddressString(), mintAmount.toString()) + await token.mint(wallet.getAddressString(), mintAmount.toString()) } - const stakeTokenWallet = this.stakeToken.connect(this.stakeToken.provider.getSigner(wallet.getAddressString())) - await stakeTokenWallet.approve(this.stakeManager.address, mintAmount.toString()) + const tokenWallet = token.connect(token.provider.getSigner(wallet.getAddressString())) + await tokenWallet.approve(this.stakeManager.address, mintAmount.toString()) const stakeManagerWallet = this.stakeManager.connect(this.stakeManager.provider.getSigner(wallet.getAddressString())) - await stakeManagerWallet.stakeFor( - wallet.getAddressString(), - stakeAmount.toString(), - fee.toString(), - acceptDelegation, - signer || wallet.getPublicKeyString() - ) + + if (legacy) { + await stakeManagerWallet.stakeForLegacy( + wallet.getAddressString(), + stakeAmount.toString(), + fee.toString(), + acceptDelegation, + signer || wallet.getPublicKeyString() + ) + } else { + await stakeManagerWallet.stakeFor( + wallet.getAddressString(), + stakeAmount.toString(), + fee.toString(), + acceptDelegation, + signer || wallet.getPublicKeyString() + ) + } + } From bed9c4224190371cc9b474f38d8ad38bc3649cc7 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Fri, 7 Jun 2024 17:30:22 +0200 Subject: [PATCH 12/92] fix: contracts --- contracts/common/misc/Migration.sol | 4 ++-- contracts/staking/stakeManager/StakeManagerStorage.sol | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/common/misc/Migration.sol b/contracts/common/misc/Migration.sol index 41d8e348..d7e78419 100644 --- a/contracts/common/misc/Migration.sol +++ b/contracts/common/misc/Migration.sol @@ -19,12 +19,12 @@ contract PolygonMigration is IPolygonMigration { bool public unmigrationLocked; modifier onlyUnmigrationUnlocked() { - require(unmigrationLocked, "UnmigrationLocked"); + require(!unmigrationLocked, "UnmigrationLocked"); _; } modifier onlyOwner() { - require(unmigrationLocked, "UnmigrationLocked"); + require(msg.sender == owner, "Only owner"); _; } diff --git a/contracts/staking/stakeManager/StakeManagerStorage.sol b/contracts/staking/stakeManager/StakeManagerStorage.sol index c25e6079..2bd42f42 100644 --- a/contracts/staking/stakeManager/StakeManagerStorage.sol +++ b/contracts/staking/stakeManager/StakeManagerStorage.sol @@ -97,5 +97,5 @@ contract StakeManagerStorage is GovernanceLockable, RootChainable { // @note does this conflict with StakeManagerStorageExtension? IERC20 public tokenLegacy; // TODO Set MATIC and POL on reinitialization (setStakingToken). - IPolygonMigration migration; + IPolygonMigration public migration; } From 5c148f9098154173a5ab8f7b3ed30b5946c1bf87 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Fri, 7 Jun 2024 17:33:02 +0200 Subject: [PATCH 13/92] feat: tests for validatorshare --- .../staking/ValidatorShareLegacy.test.js | 1696 +++++++++++++++++ 1 file changed, 1696 insertions(+) create mode 100644 test/units/staking/ValidatorShareLegacy.test.js diff --git a/test/units/staking/ValidatorShareLegacy.test.js b/test/units/staking/ValidatorShareLegacy.test.js new file mode 100644 index 00000000..3c89dde4 --- /dev/null +++ b/test/units/staking/ValidatorShareLegacy.test.js @@ -0,0 +1,1696 @@ +import {Migration, TestToken, ValidatorShare, StakingInfo, EventsHub } from '../../helpers/artifacts.js' +import testHelpers from '@openzeppelin/test-helpers' +import { checkPoint, assertBigNumberEquality, updateSlashedAmounts, assertInTransaction } from '../../helpers/utils.js' +import { wallets, freshDeploy, approveAndStake } from './deployment.js' +import { buyVoucherLegacy, sellVoucherLegacy, sellVoucherNewLegacy } from './ValidatorShareHelper.js' +const BN = testHelpers.BN +const expectRevert = testHelpers.expectRevert +const toWei = web3.utils.toWei +const ZeroAddr = '0x0000000000000000000000000000000000000000' +const ExchangeRatePrecision = new BN('100000000000000000000000000000') +const Dynasty = 8 +const ValidatorDefaultStake = new BN(toWei('100')) + +describe('ValidatorShareLegacy', function () { + const wei100 = toWei('100') + + async function slash(slashes = [], validators = [], proposer = wallets[1], nonce = 1) { + let slashingInfoList = [] + for (const slash of slashes) { + slashingInfoList.push([parseInt(slash.validator), slash.amount, '0x0']) + } + + return updateSlashedAmounts(validators, proposer, nonce, slashingInfoList, this.slashingManager) + } + + async function doDeploy() { + await freshDeploy.call(this) + + this.stakeToken = await TestToken.deploy('POL', 'POL') + this.legacyToken = await TestToken.deploy('MATIC', 'MATIC') + + this.migration = await Migration.deploy(this.legacyToken.address, this.stakeToken.address) + + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('setStakingToken', [this.stakeToken.address]) + ) + + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('setLegacyToken', [this.legacyToken.address]) + ) + + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('setMigration', [this.migration.address]) + ) + + await this.stakeToken.mint(this.stakeManager.address, toWei('10000000')) + await this.legacyToken.mint(this.stakeManager.address, toWei('10000000')) + + await this.stakeToken.mint(this.migration.address, toWei('30000000')) + await this.legacyToken.mint(this.migration.address, toWei('40000000')) + + this.validatorId = '8' + this.validatorUser = wallets[0] + this.stakeAmount = ValidatorDefaultStake + + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('updateDynastyValue', [Dynasty]) + ) + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('updateValidatorThreshold', [8]) + ) + + // we need to increase validator id beyond foundation id, repeat 7 times + for (let i = 0; i < 7; ++i) { + await approveAndStake.call(this, { + wallet: this.validatorUser, + stakeAmount: this.stakeAmount, + acceptDelegation: true, + legacy: true + }) + + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('forceUnstakeLegacy', [i + 1]) + ) + await this.stakeManager.forceFinalizeCommit() + await this.stakeManager.advanceEpoch(Dynasty) + const stakeManagerValidator = this.stakeManager.connect( + this.stakeManager.provider.getSigner(this.validatorUser.getChecksumAddressString()) + ) + await stakeManagerValidator.unstakeClaimLegacy(i + 1) + await this.stakeManager.resetSignerUsed(this.validatorUser.getChecksumAddressString()) + } + + await approveAndStake.call(this, { + wallet: this.validatorUser, + stakeAmount: this.stakeAmount, + acceptDelegation: true, + legacy: true + }) + await this.stakeManager.forceFinalizeCommit() + + let validator = await this.stakeManager.validators(this.validatorId) + this.validatorContract = await ValidatorShare.attach(validator.contractAddress) + } + + + function deployAliceAndBob() { + before(doDeploy) + before('Alice & Bob', async function () { + this.alice = wallets[2].getChecksumAddressString() + this.bob = wallets[3].getChecksumAddressString() + this.totalStaked = new BN(0) + + const mintAmount = new BN(toWei('70000')).toString() + + await this.legacyToken.mint(this.alice, mintAmount) + + const legacyTokenAlice = this.legacyToken.connect(this.legacyToken.provider.getSigner(this.alice)) + await legacyTokenAlice.approve(this.stakeManager.address, mintAmount) + + await this.legacyToken.mint(this.bob, mintAmount) + + const legacyTokenBob = this.legacyToken.connect(this.legacyToken.provider.getSigner(this.bob)) + await legacyTokenBob.approve(this.stakeManager.address, mintAmount) + }) + } + + describe('buyVoucher', function () { + function testbuyVoucherLegacy({ + voucherValue, + voucherValueExpected, + userTotalStaked, + totalStaked, + shares, + reward, + initialBalance + }) { + it('must buy voucher', async function () { + this.receipt = await (await buyVoucherLegacy(this.validatorContract, voucherValue, this.user, shares)).wait() + }) + + shouldBuyShares({ + voucherValueExpected, + shares, + totalStaked + }) + + shouldHaveCorrectStakes({ + userTotalStaked, + totalStaked + }) + + shouldWithdrawReward({ + initialBalance, + reward, + validatorId: '8' + }) + } + + describe('when Alice purchases voucher once', function () { + deployAliceAndBob() + + before(function () { + this.user = this.alice + }) + + testbuyVoucherLegacy({ + voucherValue: toWei('100'), + voucherValueExpected: toWei('100'), + userTotalStaked: toWei('100'), + totalStaked: toWei('200'), + shares: toWei('100'), + reward: '0', + initialBalance: toWei('69900') + }) + }) + + describe('when Alice purchases voucher with exact minSharesToMint', function () { + deployAliceAndBob() + + before(function () { + this.user = this.alice + }) + + testbuyVoucherLegacy({ + voucherValue: toWei('100'), + voucherValueExpected: toWei('100'), + userTotalStaked: toWei('100'), + totalStaked: toWei('200'), + shares: toWei('100'), + reward: '0', + initialBalance: toWei('69900') + }) + }) + + describe('when validator turns off delegation', function () { + deployAliceAndBob() + + before('disable delegation', async function () { + const stakeManagerValidator = this.stakeManager.connect( + this.stakeManager.provider.getSigner(this.validatorUser.getChecksumAddressString()) + ) + await stakeManagerValidator.updateValidatorDelegation(false) + }) + + it('reverts', async function () { + await expectRevert(buyVoucherLegacy(this.validatorContract, toWei('150'), this.alice), 'Delegation is disabled') + }) + }) + + describe('when staking manager delegation is disabled', function () { + deployAliceAndBob() + + before('disable delegation', async function () { + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('setDelegationEnabled', [false]) + ) + }) + + it('reverts', async function () { + await expectRevert( + buyVoucherLegacy(this.validatorContract, web3.utils.toWei('150'), this.alice), + 'Delegation is disabled' + ) + }) + }) + + describe('when Alice purchases voucher 3 times in a row, no checkpoints inbetween', function () { + deployAliceAndBob() + + before(function () { + this.user = this.alice + }) + + describe('1st purchase', async function () { + testbuyVoucherLegacy({ + voucherValue: toWei('100'), + voucherValueExpected: toWei('100'), + userTotalStaked: toWei('100'), + totalStaked: toWei('200'), + shares: toWei('100'), + reward: '0', + initialBalance: toWei('69900') + }) + }) + + describe('2nd purchase', async function () { + testbuyVoucherLegacy({ + voucherValue: toWei('150'), + voucherValueExpected: toWei('150'), + userTotalStaked: toWei('250'), + totalStaked: toWei('350'), + shares: toWei('150'), + reward: '0', + initialBalance: toWei('69750') + }) + }) + + describe('3rd purchase', async function () { + testbuyVoucherLegacy({ + voucherValue: toWei('250'), + voucherValueExpected: toWei('250'), + userTotalStaked: toWei('500'), + totalStaked: toWei('600'), + shares: toWei('250'), + reward: '0', + initialBalance: toWei('69500') + }) + }) + }) + + describe('when Alice purchases voucher 3 times in a row, 1 checkpoint inbetween', function () { + function advanceCheckpointAfter() { + after(async function () { + await checkPoint([this.validatorUser], this.rootChainOwner, this.stakeManager) + }) + } + + deployAliceAndBob() + + before(function () { + this.user = this.alice + }) + + describe('1st purchase', async function () { + advanceCheckpointAfter() + + testbuyVoucherLegacy({ + voucherValue: toWei('100'), + voucherValueExpected: toWei('100'), + userTotalStaked: toWei('100'), + totalStaked: toWei('200'), + shares: toWei('100'), + reward: '0', + initialBalance: toWei('69900') + }) + }) + + describe('2nd purchase', async function () { + advanceCheckpointAfter() + + testbuyVoucherLegacy({ + voucherValue: toWei('150'), + voucherValueExpected: toWei('150'), + userTotalStaked: toWei('250'), + totalStaked: toWei('350'), + shares: toWei('150'), + reward: toWei('4500'), + initialBalance: toWei('69750') + }) + }) + + describe('3rd purchase', async function () { + testbuyVoucherLegacy({ + voucherValue: toWei('250'), + voucherValueExpected: toWei('250'), + userTotalStaked: toWei('500'), + totalStaked: toWei('600'), + shares: toWei('250'), + reward: '6428571428571428571428', + initialBalance: toWei('74000') + }) + }) + }) + + describe('when Alice and Bob purchase vouchers, no checkpoints inbetween', function () { + deployAliceAndBob() + + describe('when Alice stakes 1st time', function () { + before(function () { + this.user = this.alice + }) + + testbuyVoucherLegacy({ + voucherValue: toWei('100'), + voucherValueExpected: toWei('100'), + userTotalStaked: toWei('100'), + totalStaked: toWei('200'), + shares: toWei('100'), + reward: '0', + initialBalance: toWei('69900') + }) + }) + + describe('when Bob stakes 1st time', function () { + before(function () { + this.user = this.bob + }) + + testbuyVoucherLegacy({ + voucherValue: toWei('100'), + voucherValueExpected: toWei('100'), + userTotalStaked: toWei('100'), + totalStaked: toWei('300'), + shares: toWei('100'), + reward: '0', + initialBalance: toWei('69900') + }) + }) + + describe('when Alice stakes 2nd time', function () { + before(function () { + this.user = this.alice + }) + + testbuyVoucherLegacy({ + voucherValue: toWei('200'), + voucherValueExpected: toWei('200'), + userTotalStaked: toWei('300'), + totalStaked: toWei('500'), + shares: toWei('200'), + reward: '0', + initialBalance: toWei('69700') + }) + }) + + describe('when Bob stakes 2nd time', function () { + before(function () { + this.user = this.bob + }) + + testbuyVoucherLegacy({ + voucherValue: toWei('200'), + voucherValueExpected: toWei('200'), + userTotalStaked: toWei('300'), + totalStaked: toWei('700'), + shares: toWei('200'), + reward: '0', + initialBalance: toWei('69700') + }) + }) + }) + + describe('when Alice and Bob purchase vouchers, 1 checkpoint inbetween', function () { + function advanceCheckpointAfter() { + after(async function () { + await checkPoint([this.validatorUser], this.rootChainOwner, this.stakeManager) + }) + } + + deployAliceAndBob() + + describe('when Alice stakes 1st time', function () { + advanceCheckpointAfter() + before(function () { + this.user = this.alice + }) + + testbuyVoucherLegacy({ + voucherValue: toWei('100'), + voucherValueExpected: toWei('100'), + userTotalStaked: toWei('100'), + totalStaked: toWei('200'), + shares: toWei('100'), + reward: '0', + initialBalance: toWei('69900') + }) + }) + + describe('when Bob stakes 1st time', function () { + advanceCheckpointAfter() + before(function () { + this.user = this.bob + }) + + testbuyVoucherLegacy({ + voucherValue: toWei('100'), + voucherValueExpected: toWei('100'), + userTotalStaked: toWei('100'), + totalStaked: toWei('300'), + shares: toWei('100'), + reward: '0', + initialBalance: toWei('69900') + }) + }) + + describe('when Alice stakes 2nd time', function () { + advanceCheckpointAfter() + before(function () { + this.user = this.alice + }) + + testbuyVoucherLegacy({ + voucherValue: toWei('200'), + voucherValueExpected: toWei('200'), + userTotalStaked: toWei('300'), + totalStaked: toWei('500'), + shares: toWei('200'), + reward: toWei('7500'), + initialBalance: toWei('69700') + }) + }) + + describe('when Bob stakes 2nd time', function () { + before(function () { + this.user = this.bob + }) + + testbuyVoucherLegacy({ + voucherValue: toWei('200'), + voucherValueExpected: toWei('200'), + userTotalStaked: toWei('300'), + totalStaked: toWei('700'), + shares: toWei('200'), + reward: toWei('4800'), + initialBalance: toWei('69700') + }) + }) + }) + + describe('when locked', function () { + deployAliceAndBob() + + before(async function () { + await this.stakeManager.testLockShareContract(this.validatorId, true) + }) + + it('reverts', async function () { + await expectRevert(buyVoucherLegacy(this.validatorContract, toWei('100'), this.alice, toWei('100')), 'locked') + }) + }) + + describe('when validator unstaked', function () { + deployAliceAndBob() + before(async function () { + const stakeManagerValidator = this.stakeManager.connect( + this.stakeManager.provider.getSigner(this.validatorUser.getChecksumAddressString()) + ) + await stakeManagerValidator.unstake(this.validatorId) + await this.stakeManager.advanceEpoch(Dynasty) + }) + + it('reverts', async function () { + await expectRevert(buyVoucherLegacy(this.validatorContract, new BN(toWei('100')), this.alice), 'locked') + }) + }) + }) + + describe('exchangeRate', function () { + describe('when Alice purchases voucher 2 times, 1 epoch between', function () { + before(doDeploy) + + before(async function () { + this.user = wallets[2].getAddressString() + this.totalStaked = new BN(0) + + const voucherAmount = new BN(toWei('70000')).toString() + await this.legacyToken.mint(this.user, voucherAmount) + const legacyTokenUser = this.legacyToken.connect(this.legacyToken.provider.getSigner(this.user)) + await legacyTokenUser.approve(this.stakeManager.address, voucherAmount) + }) + + it('must buy voucher', async function () { + const voucherValue = toWei('100') + this.totalStaked = this.totalStaked.add(new BN(voucherValue)) + + await buyVoucherLegacy(this.validatorContract, voucherValue, this.user) + }) + + it('exchange rate must be correct', async function () { + assertBigNumberEquality(await this.validatorContract.exchangeRate(), ExchangeRatePrecision) + }) + + it('must buy another voucher 1 epoch later', async function () { + await checkPoint([this.validatorUser], this.rootChainOwner, this.stakeManager) + + const voucherValue = toWei('5000') + this.totalStaked = this.totalStaked.add(new BN(voucherValue)) + await buyVoucherLegacy(this.validatorContract, voucherValue, this.user) + }) + + it('exchange rate must be correct', async function () { + assertBigNumberEquality(await this.validatorContract.exchangeRate(), ExchangeRatePrecision) + }) + }) + + describe('when Alice purchases voucher and sells it', function () { + before(doDeploy) + before(async function () { + this.user = wallets[2].getAddressString() + await this.legacyToken.mint(this.user, toWei('250')) + + this.beforeExchangeRate = await this.validatorContract.exchangeRate() + const legacyTokenUser = this.legacyToken.connect(this.legacyToken.provider.getSigner(this.user)) + await legacyTokenUser.approve(this.stakeManager.address, toWei('250')) + }) + + it('must purchase voucher', async function () { + await buyVoucherLegacy(this.validatorContract, toWei('100'), this.user) + }) + + it('must sell voucher', async function () { + await sellVoucherLegacy(this.validatorContract, this.user) + }) + + it('must have initial exchange rate', async function () { + let afterExchangeRate = await this.validatorContract.exchangeRate() + assertBigNumberEquality(afterExchangeRate, this.beforeExchangeRate) + }) + }) + }) + + describe('sellVoucher', function () { + const aliceStake = new BN(toWei('100')) + const bobStake = new BN(toWei('200')) + const Alice = wallets[2].getChecksumAddressString() + const Bob = wallets[1].getChecksumAddressString() + + async function doDeployAndBuyVoucherForAliceAndBob(includeBob = false) { + await doDeploy.call(this) + + const stake = async ({ user, stake }) => { + await this.legacyToken.mint(user, stake) + const legacyTokenUser = this.legacyToken.connect(this.legacyToken.provider.getSigner(user)) + await legacyTokenUser.approve(this.stakeManager.address, stake) + await buyVoucherLegacy(this.validatorContract, stake, user) + } + + await stake({ user: Alice, stake: aliceStake.toString() }) + + if (includeBob) { + await stake({ user: Bob, stake: bobStake.toString() }) + } + + for (let i = 0; i < 4; i++) { + await checkPoint([this.validatorUser], this.rootChainOwner, this.stakeManager) + } + } + + function testSellVoucherLegacyNew({ + returnedStake, + reward, + initialBalance, + validatorId, + user, + minClaimAmount, + userTotalStaked, + totalStaked, + shares, + nonce, + withdrawalExchangeRate = ExchangeRatePrecision + }) { + if (minClaimAmount) { + it('must sell voucher with slippage', async function () { + this.receipt = await (await sellVoucherNewLegacy(this.validatorContract, user, minClaimAmount)).wait() + }) + } else { + it('must sell voucher', async function () { + this.receipt = await (await sellVoucherNewLegacy(this.validatorContract, user)).wait() + }) + } + + if (nonce) { + it('must emit ShareBurnedWithId', async function () { + assertInTransaction(this.receipt, EventsHub, 'ShareBurnedWithId', { + validatorId: validatorId, + tokens: shares.toString(), + amount: returnedStake.toString(), + user: user, + nonce + }) + }) + } else { + it('must emit ShareBurned', async function () { + assertInTransaction(this.receipt, StakingInfo, 'ShareBurned', { + validatorId: validatorId, + tokens: shares, + amount: returnedStake, + user: user + }) + }) + } + + shouldWithdrawReward({ initialBalance, validatorId, user, reward }) + + shouldHaveCorrectStakes({ + userTotalStaked, + totalStaked, + user + }) + + it('must have correct withdrawal exchange rate', async function () { + const rate = await this.validatorContract.withdrawExchangeRate() + assertBigNumberEquality(rate, withdrawalExchangeRate) + }) + } + + function testSellVoucherLegacy({ + returnedStake, + reward, + initialBalance, + validatorId, + user, + minClaimAmount, + userTotalStaked, + totalStaked, + shares, + withdrawalExchangeRate = ExchangeRatePrecision + }) { + if (minClaimAmount) { + it('must sell voucher with slippage', async function () { + this.receipt = await (await sellVoucherLegacy(this.validatorContract, user, minClaimAmount.toString())).wait() + }) + } else { + it('must sell voucher', async function () { + this.receipt = await (await sellVoucherLegacy(this.validatorContract, user)).wait() + }) + } + + it('must emit ShareBurned', async function () { + assertInTransaction(this.receipt, StakingInfo, 'ShareBurned', { + validatorId: validatorId, + tokens: shares.toString(), + amount: returnedStake.toString(), + user: user + }) + }) + + shouldWithdrawReward({ initialBalance, validatorId, user, reward }) + + shouldHaveCorrectStakes({ + userTotalStaked, + totalStaked, + user + }) + + it('must have correct withdrawal exchange rate', async function () { + const rate = await this.validatorContract.withdrawExchangeRate() + assertBigNumberEquality(rate, withdrawalExchangeRate) + }) + } + + describe('when Alice sells voucher', function () { + before(doDeployAndBuyVoucherForAliceAndBob) + + testSellVoucherLegacy({ + returnedStake: aliceStake, + reward: toWei('18000'), + initialBalance: new BN(0), + validatorId: '8', + user: Alice, + userTotalStaked: toWei('0'), + totalStaked: ValidatorDefaultStake, + shares: aliceStake + }) + }) + + describe('when delegation is disabled after voucher was purchased by Alice', function () { + before(doDeployAndBuyVoucherForAliceAndBob) + before('disable delegation', async function () { + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('setDelegationEnabled', [false]) + ) + }) + + testSellVoucherLegacy({ + returnedStake: aliceStake, + reward: toWei('18000'), + initialBalance: new BN(0), + validatorId: '8', + user: Alice, + userTotalStaked: toWei('0'), + totalStaked: ValidatorDefaultStake, + shares: aliceStake + }) + }) + + describe('when Alice sells with claimAmount greater than expected', function () { + before(doDeployAndBuyVoucherForAliceAndBob) + + it('reverts', async function () { + const maxShares = await this.validatorContract.balanceOf(Alice) + const validatorAlice = this.validatorContract.connect(this.validatorContract.provider.getSigner(Alice)) + await expectRevert(validatorAlice.sellVoucherLegacy(toWei('100.00001'), maxShares), 'Too much requested') + }) + }) + + describe('when locked', function () { + before(doDeployAndBuyVoucherForAliceAndBob) + + before(async function () { + await this.stakeManager.testLockShareContract(this.validatorId, true) + }) + + testSellVoucherLegacy({ + returnedStake: aliceStake, + reward: toWei('18000'), + initialBalance: new BN(0), + validatorId: '8', + user: Alice, + userTotalStaked: toWei('0'), + totalStaked: ValidatorDefaultStake, + shares: aliceStake + }) + }) + + describe('when validator unstaked', function () { + before(doDeployAndBuyVoucherForAliceAndBob) + before(async function () { + const stakeManagerValidator = this.stakeManager.connect( + this.stakeManager.provider.getSigner(this.validatorUser.getChecksumAddressString()) + ) + await stakeManagerValidator.unstake(this.validatorId) + await this.stakeManager.advanceEpoch(Dynasty) + }) + + testSellVoucherLegacy({ + returnedStake: aliceStake, + reward: toWei('18000'), + initialBalance: new BN(0), + validatorId: '8', + user: Alice, + userTotalStaked: toWei('0'), + totalStaked: 0, + shares: aliceStake + }) + }) + + describe('when Alice and Bob sell within withdrawal delay', function () { + before(async function () { + await doDeployAndBuyVoucherForAliceAndBob.call(this, true) + }) + + describe('when Alice sells', function () { + testSellVoucherLegacy({ + returnedStake: aliceStake, + reward: toWei('9000'), + initialBalance: new BN(0), + validatorId: '8', + user: Alice, + userTotalStaked: toWei('0'), + shares: aliceStake, + totalStaked: new BN(bobStake).add(ValidatorDefaultStake) + }) + }) + + describe('when Bob sells', function () { + testSellVoucherLegacy({ + returnedStake: bobStake, + reward: toWei('18000'), + initialBalance: new BN(0), + validatorId: '8', + user: Bob, + userTotalStaked: toWei('0'), + shares: bobStake, + totalStaked: ValidatorDefaultStake + }) + }) + }) + + describe('partial sell', function () { + describe('new API', function () { + describe('when Alice is not slashed', function () { + before(doDeployAndBuyVoucherForAliceAndBob) + + const halfStake = aliceStake.div(new BN('2')) + + describe('when Alice sells 50%', function () { + testSellVoucherLegacyNew({ + shares: new BN(toWei('50')), + minClaimAmount: halfStake, + returnedStake: halfStake, + reward: toWei('18000'), + initialBalance: new BN(0), + validatorId: '8', + user: Alice, + userTotalStaked: halfStake, + nonce: '1', + totalStaked: halfStake.add(ValidatorDefaultStake) + }) + }) + + describe('when Alice sells 50%, after 1 epoch, within withdrawal delay', function () { + before(async function () { + await this.stakeManager.advanceEpoch(1) + }) + + testSellVoucherLegacyNew({ + shares: new BN(toWei('50')), + minClaimAmount: halfStake, + returnedStake: halfStake, + reward: '0', + initialBalance: new BN(toWei('18000')), + validatorId: '8', + user: Alice, + userTotalStaked: '0', + nonce: '2', + totalStaked: ValidatorDefaultStake + }) + }) + }) + }) + + describe('old API', function () { + describe('when Alice is not slashed', function () { + before(doDeployAndBuyVoucherForAliceAndBob) + + const halfStake = aliceStake.div(new BN('2')) + + describe('when Alice sells 50%', function () { + testSellVoucherLegacy({ + shares: new BN(toWei('50')).toString(), + minClaimAmount: halfStake, + returnedStake: halfStake, + reward: toWei('18000'), + initialBalance: new BN(0), + validatorId: '8', + user: Alice, + userTotalStaked: halfStake, + totalStaked: halfStake.add(ValidatorDefaultStake) + }) + }) + + describe('when Alice sells 50%, after 1 epoch, within withdrawal delay', function () { + before(async function () { + await this.stakeManager.advanceEpoch(1) + }) + + testSellVoucherLegacy({ + shares: new BN(toWei('50')), + minClaimAmount: halfStake, + returnedStake: halfStake, + reward: '0', + initialBalance: new BN(toWei('18000')), + validatorId: '8', + user: Alice, + userTotalStaked: '0', + totalStaked: ValidatorDefaultStake + }) + + it('unbond epoch must be set to current epoch', async function () { + const unbond = await this.validatorContract.unbonds(Alice) + assertBigNumberEquality(unbond.withdrawEpoch, await this.stakeManager.currentEpoch()) + }) + }) + }) + }) + }) + }) + + describe('withdrawRewards', function () { + const Alice = wallets[2].getChecksumAddressString() + const Bob = wallets[3].getChecksumAddressString() + const Eve = wallets[4].getChecksumAddressString() + const Carol = wallets[5].getChecksumAddressString() + + let totalDelegatorRewardsReceived + let totalSlashed + let totalStaked + let totalInitialBalance + let delegators = [] + + function testWithdraw({ label, user, expectedReward, initialBalance }) { + describe(`when ${label} withdraws`, function () { + if (expectedReward.toString() === '0') { + it('reverts', async function () { + const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(user)) + await expectRevert(validatorUser.withdrawRewardsLegacy(), 'Too small rewards amount') + }) + } else { + it('must withdraw rewards', async function () { + const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(user)) + this.receipt = await (await validatorUser.withdrawRewardsLegacy()).wait() + }) + + shouldWithdrawReward({ + reward: expectedReward, + user: user, + validatorId: '8', + initialBalance: initialBalance + }) + } + }) + } + + function testSlash({ amount, nonce }) { + describe('Slash', function () { + it(`${amount.toString()} wei`, async function () { + await slash.call( + this, + [{ validator: this.validatorId, amount: amount }], + [this.validatorUser], + this.validatorUser, + nonce + ) + totalSlashed = totalSlashed.add(new BN(amount)) + }) + }) + } + + function testStake({ user, amount, label, initialBalance = new BN(0) }) { + describe(`${label} buyVoucher for ${amount.toString()} wei`, function () { + it(`must purchase voucher`, async function () { + totalInitialBalance = totalInitialBalance.add(initialBalance) + totalStaked = totalStaked.add(new BN(amount)) + + await this.legacyToken.mint(user, amount.toString()) + const legacyTokenUser = this.legacyToken.connect(this.legacyToken.provider.getSigner(user)) + await legacyTokenUser.approve(this.stakeManager.address, amount.toString()) + await buyVoucherLegacy(this.validatorContract, amount.toString(), user) + delegators[user] = delegators[user] || { + rewards: new BN(0) + } + }) + + it('must have correct initalRewardPerShare', async function () { + const currentRewardPerShare = await this.validatorContract.getRewardPerShare() + const userRewardPerShare = await this.validatorContract.initalRewardPerShare(user) + assertBigNumberEquality(currentRewardPerShare, userRewardPerShare) + }) + }) + } + + function testCheckpoint(checkpoints) { + describe('checkpoints', function () { + it(`${checkpoints} more checkpoint(s)`, async function () { + let c = 0 + while (c++ < checkpoints) { + await checkPoint([this.validatorUser], this.rootChainOwner, this.stakeManager) + } + + totalDelegatorRewardsReceived = new ethers.BigNumber.from(0) + for (const user in delegators) { + const rewards = await this.validatorContract.getLiquidRewards(user) + totalDelegatorRewardsReceived = totalDelegatorRewardsReceived.add(rewards) + } + }) + }) + } + + function testLiquidRewards({ user, label, expectedReward }) { + describe(`${label} liquid rewards`, function () { + it(`${expectedReward.toString()}`, async function () { + const rewards = await this.validatorContract.getLiquidRewards(user) + assertBigNumberEquality(rewards, expectedReward) + }) + }) + } + + function testAllRewardsReceived({ validatorReward, totalExpectedRewards }) { + async function getValidatorReward() { + return this.stakeManager.validatorReward(this.validatorId) + } + + describe('total rewards', function () { + it(`validator rewards == ${validatorReward.toString()}`, async function () { + assertBigNumberEquality(await getValidatorReward.call(this), validatorReward) + }) + + it(`all expected rewards should be ${totalExpectedRewards.toString()}`, async function () { + const validatorRewards = await getValidatorReward.call(this) + assertBigNumberEquality(validatorRewards.add(totalDelegatorRewardsReceived.toString()), totalExpectedRewards) + }) + + it(`total received rewards must be correct`, async function () { + const validatorRewards = await getValidatorReward.call(this) + const totalReceived = validatorRewards.add(totalDelegatorRewardsReceived.toString()) + + const stakeManagerValidator = this.stakeManager.connect( + this.stakeManager.provider.getSigner(this.validatorUser.getChecksumAddressString()) + ) + await stakeManagerValidator.withdrawRewardsLegacy(this.validatorId) + + const tokensLeft = await this.stakeToken.balanceOf(this.stakeManager.address) + + assertBigNumberEquality( + this.initialStakeTokenBalance + .add(totalStaked.toString()) + .sub(totalReceived) + .sub(totalInitialBalance.toString()) + .sub(totalSlashed.toString()), + tokensLeft + ) + }) + }) + } + + function runWithdrawRewardsTest(timeline) { + before(doDeploy) + before(async function () { + delegators = {} + totalInitialBalance = new BN(0) + totalStaked = new BN(0) + totalSlashed = new BN(0) + totalDelegatorRewardsReceived = new BN(0) + this.initialStakeTokenBalance = await this.stakeToken.balanceOf(this.stakeManager.address) + }) + + for (const step of timeline) { + if (step.slash) { + testSlash(step.slash) + } else if (step.stake) { + testStake(step.stake) + } else if (step.checkpoints) { + testCheckpoint(step.checkpoints) + } else if (step.withdraw) { + testWithdraw(step.withdraw) + } else if (step.liquidRewards) { + testLiquidRewards(step.liquidRewards) + } else if (step.allRewards) { + testAllRewardsReceived(step.allRewards) + } + } + } + + describe('when Alice purchases voucher after checkpoint', function () { + runWithdrawRewardsTest([ + { checkpoints: 1 }, + { stake: { user: Alice, label: 'Alice', amount: new BN(wei100) } }, + { withdraw: { user: Alice, label: 'Alice', expectedReward: '0' } }, + { allRewards: { validatorReward: toWei('9000'), totalExpectedRewards: toWei('9000') } } + ]) + }) + + describe('when Alice is not slashed. 1 checkpoint passed', function () { + runWithdrawRewardsTest([ + { stake: { user: Alice, label: 'Alice', amount: new BN(wei100) } }, + { checkpoints: 1 }, + { withdraw: { user: Alice, label: 'Alice', expectedReward: toWei('4500') } }, + { allRewards: { validatorReward: toWei('4500'), totalExpectedRewards: toWei('9000') } } + ]) + }) + + describe('Alice, Bob, Eve and Carol stake #1', function () { + runWithdrawRewardsTest([ + { stake: { user: Alice, label: 'Alice', amount: new BN(toWei('100')) } }, + { checkpoints: 1 }, + { liquidRewards: { user: Alice, label: 'Alice', expectedReward: toWei('4500') } }, + { stake: { user: Bob, label: 'Bob', amount: new BN(toWei('500')) } }, + { slash: { amount: new BN(toWei('350')) } }, + { checkpoints: 1 }, + { liquidRewards: { user: Alice, label: 'Alice', expectedReward: '5785714285714285714285' } }, + { liquidRewards: { user: Bob, label: 'Bob', expectedReward: '6428571428571428571428' } }, + { stake: { user: Carol, label: 'Carol', amount: new BN(toWei('500')) } }, + { checkpoints: 1 }, + { liquidRewards: { user: Alice, label: 'Alice', expectedReward: '6315126050420168067226' } }, + { liquidRewards: { user: Bob, label: 'Bob', expectedReward: '9075630252100840336133' } }, + { liquidRewards: { user: Carol, label: 'Carol', expectedReward: '5294117647058823529411' } }, + { slash: { amount: new BN(toWei('167')), nonce: 2 } }, + { stake: { user: Eve, label: 'Eve', amount: new BN(toWei('500')), initialBalance: new BN(1) } }, + { checkpoints: 1 }, + { withdraw: { user: Alice, label: 'Alice', expectedReward: '6620779672815871910894' } }, + { withdraw: { user: Bob, label: 'Bob', expectedReward: '10603898364079359554473' } }, + { withdraw: { user: Carol, label: 'Carol', expectedReward: '8350653871015861966090' } }, + { withdraw: { user: Eve, label: 'Eve', expectedReward: '3803888419273034657649', initialBalance: new BN(1) } }, + { allRewards: { validatorReward: '6620779672815871910888', totalExpectedRewards: '35999999999999999999994' } } + ]) + }) + + describe('Alice, Bob, Eve and Carol stake #2', function () { + runWithdrawRewardsTest([ + { stake: { user: Alice, label: 'Alice', amount: new BN(toWei('100')) } }, + { checkpoints: 1 }, + { liquidRewards: { user: Alice, label: 'Alice', expectedReward: toWei('4500') } }, + { stake: { user: Bob, label: 'Bob', amount: new BN(toWei('500')) } }, + { slash: { amount: new BN(toWei('350')) } }, + { checkpoints: 1 }, + { liquidRewards: { user: Alice, label: 'Alice', expectedReward: '5785714285714285714285' } }, + { liquidRewards: { user: Bob, label: 'Bob', expectedReward: '6428571428571428571428' } }, + { stake: { user: Carol, label: 'Carol', amount: new BN(toWei('500')) } }, + { slash: { amount: new BN(toWei('425')), nonce: 2 } }, + { checkpoints: 1 }, + { liquidRewards: { user: Alice, label: 'Alice', expectedReward: '6315126050420168067226' } }, + { liquidRewards: { user: Bob, label: 'Bob', expectedReward: '9075630252100840336133' } }, + { liquidRewards: { user: Carol, label: 'Carol', expectedReward: '5294117647058823529411' } }, + { slash: { amount: new BN(toWei('215')), nonce: 3 } }, + { stake: { user: Eve, label: 'Eve', amount: new BN(toWei('500')), initialBalance: new BN(1) } }, + { checkpoints: 1 }, + { withdraw: { user: Alice, label: 'Alice', expectedReward: '6471712628713457213871' } }, + { withdraw: { user: Bob, label: 'Bob', expectedReward: '9858563143567286069357' } }, + { withdraw: { user: Carol, label: 'Carol', expectedReward: '6859983429991714995859' } }, + { withdraw: { user: Eve, label: 'Eve', expectedReward: '6338028169014084507041', initialBalance: new BN(1) } }, + { allRewards: { validatorReward: '6471712628713457213867', totalExpectedRewards: '35999999999999999999995' } } + ]) + }) + + describe('when not enough rewards', function () { + before(doDeploy) + + it('reverts', async function () { + const validatorContractAlice = this.validatorContract.connect(this.validatorContract.provider.getSigner(Alice)) + await expectRevert(validatorContractAlice.withdrawRewardsLegacy(), 'Too small rewards amount') + }) + }) + + describe('when Alice withdraws 2 times in a row', async function () { + runWithdrawRewardsTest([ + { stake: { user: Alice, label: 'Alice', amount: new BN(toWei('100')) } }, + { checkpoints: 1 }, + { withdraw: { user: Alice, label: 'Alice', expectedReward: toWei('4500') } }, + { withdraw: { user: Alice, label: 'Alice', expectedReward: '0' } } + ]) + }) + + describe('when locked', function () { + before(doDeploy) + + before(async function () { + const amount = toWei('100') + await this.legacyToken.mint(Alice, amount) + const legacyTokenAlice = this.legacyToken.connect(this.legacyToken.provider.getSigner(Alice)) + await legacyTokenAlice.approve(this.stakeManager.address, amount) + await buyVoucherLegacy(this.validatorContract, amount, Alice) + await checkPoint([this.validatorUser], this.rootChainOwner, this.stakeManager) + await this.stakeManager.testLockShareContract(this.validatorId, true) + }) + + it('must withdraw rewards', async function () { + const validatorContractAlice = this.validatorContract.connect(this.validatorContract.provider.getSigner(Alice)) + this.receipt = await (await validatorContractAlice.withdrawRewardsLegacy()).wait() + }) + + shouldWithdrawReward({ + initialBalance: new BN('0'), + validatorId: '8', + user: Alice, + reward: toWei('4500') + }) + }) + + describe('when validator unstaked', function () { + before(doDeploy) + before(async function () { + const amount = toWei('100') + await this.legacyToken.mint(Alice, amount) + const legacyTokenAlice = this.legacyToken.connect(this.legacyToken.provider.getSigner(Alice)) + await legacyTokenAlice.approve(this.stakeManager.address, amount) + await buyVoucherLegacy(this.validatorContract, amount, Alice) + await checkPoint([this.validatorUser], this.rootChainOwner, this.stakeManager) + const stakeManagerAlice = this.stakeManager.connect( + this.stakeManager.provider.getSigner(this.validatorUser.getChecksumAddressString()) + ) + await stakeManagerAlice.unstake(this.validatorId) + await this.stakeManager.advanceEpoch(Dynasty) + }) + + it('must withdraw rewards', async function () { + const validatorContractAlice = this.validatorContract.connect(this.validatorContract.provider.getSigner(Alice)) + this.receipt = await (await validatorContractAlice.withdrawRewardsLegacy()).wait() + }) + + shouldWithdrawReward({ + initialBalance: new BN('0'), + validatorId: '8', + user: Alice, + reward: toWei('4500') + }) + }) + }) + + describe('restake', function () { + function prepareForTest({ skipCheckpoint } = {}) { + before(doDeploy) + before(async function () { + this.user = wallets[2].getChecksumAddressString() + + await this.legacyToken.mint(this.user, this.stakeAmount.toString()) + const legacyTokenUser = this.legacyToken.connect(this.legacyToken.provider.getSigner(this.user)) + await legacyTokenUser.approve(this.stakeManager.address, this.stakeAmount.toString()) + + await buyVoucherLegacy(this.validatorContract, this.stakeAmount.toString(), this.user) + this.shares = await this.validatorContract.balanceOf(this.user) + + if (!skipCheckpoint) { + await checkPoint([this.validatorUser], this.rootChainOwner, this.stakeManager) + } + }) + } + + describe('when Alice restakes', function () { + const voucherValueExpected = new BN(toWei('4500')) + const reward = new BN(toWei('4500')) + const userTotalStaked = new BN(toWei('4600')) + const shares = new BN(toWei('4500')) + const totalStaked = new BN(toWei('4700')) + const initialBalance = new BN(toWei('100')) + + prepareForTest() + + it('must restake', async function () { + const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.user)) + this.receipt = await (await validatorUser.restakeLegacy()).wait() + }) + + shouldBuyShares({ + voucherValueExpected, + userTotalStaked, + totalStaked, + shares, + reward, + initialBalance + }) + + shouldWithdrawReward({ + reward: '0', // we need only partial test here, reward is not really claimed + initialBalance, + checkBalance: false, + validatorId: '8' + }) + + it('must emit DelegatorRestaked', async function () { + assertInTransaction(this.receipt, StakingInfo, 'DelegatorRestaked', { + validatorId: this.validatorId, + totalStaked: userTotalStaked.toString() + }) + }) + }) + + describe('when no liquid rewards', function () { + prepareForTest({ skipCheckpoint: true }) + + it('reverts', async function () { + const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.user)) + await expectRevert(validatorUser.restakeLegacy(), 'Too small rewards to restake') + }) + }) + + describe('when staking manager delegation is disabled', function () { + prepareForTest() + + before('disable delegation', async function () { + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('setDelegationEnabled', [false]) + ) + }) + + it('reverts', async function () { + const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.user)) + await expectRevert(validatorUser.restakeLegacy(), 'Delegation is disabled') + }) + }) + + describe('when validator unstaked', function () { + prepareForTest() + before(async function () { + const stakeManagerValidator = this.stakeManager.connect( + this.stakeManager.provider.getSigner(this.validatorUser.getChecksumAddressString()) + ) + await stakeManagerValidator.unstake(this.validatorId) + }) + + it('reverts', async function () { + const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.user)) + await expectRevert(validatorUser.restakeLegacy(), 'locked') + }) + }) + + describe('when locked', function () { + prepareForTest() + + before(async function () { + await this.stakeManager.testLockShareContract(this.validatorId, true) + }) + + it('reverts', async function () { + const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.user)) + await expectRevert(validatorUser.restakeLegacy(), 'locked') + }) + }) + }) + + describe('unstakeClaimTokens', function () { + function prepareForTest({ skipSell, skipBuy } = {}) { + before(doDeploy) + before(async function () { + this.user = wallets[2].getChecksumAddressString() + + await this.legacyToken.mint(this.user, this.stakeAmount.toString()) + const legacyTokenUser = this.legacyToken.connect(this.legacyToken.provider.getSigner(this.user)) + await legacyTokenUser.approve(this.stakeManager.address, this.stakeAmount.toString()) + + this.totalStaked = this.stakeAmount + }) + + if (!skipBuy) { + before('buy', async function () { + await buyVoucherLegacy(this.validatorContract, this.stakeAmount.toString(), this.user) + }) + } + + if (!skipSell) { + before('sell', async function () { + await sellVoucherLegacy(this.validatorContract, this.user) + }) + } + } + + describe('when Alice unstakes right after voucher sell', function () { + prepareForTest() + + before('checkpoint', async function () { + let currentEpoch = await this.stakeManager.currentEpoch() + let exitEpoch = currentEpoch.add(await this.stakeManager.WITHDRAWAL_DELAY()) + + for (let i = currentEpoch; i <= exitEpoch; i++) { + await checkPoint([this.validatorUser], this.rootChainOwner, this.stakeManager) + } + }) + + it('must unstake', async function () { + const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.user)) + this.receipt = await (await validatorUser.unstakeClaimTokensLegacy()).wait() + }) + + it('must emit DelegatorUnstaked', async function () { + assertInTransaction(this.receipt, StakingInfo, 'DelegatorUnstaked', { + validatorId: this.validatorId, + user: this.user, + amount: this.stakeAmount.toString() + }) + }) + + shouldHaveCorrectStakes({ + userTotalStaked: '0', + totalStaked: toWei('100') + }) + }) + + describe('when Alice claims too early', function () { + prepareForTest() + + it('reverts', async function () { + const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.user)) + await expectRevert( + validatorUser.unstakeClaimTokensLegacy(), + 'Incomplete withdrawal period' + ) + }) + }) + + describe('when Alice claims with 0 shares', function () { + prepareForTest({ skipSell: true }) + + it('reverts', async function () { + const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.user)) + await expectRevert( + validatorUser.unstakeClaimTokensLegacy(), + 'Incomplete withdrawal period' + ) + }) + }) + + describe("when Alice didn't buy voucher", function () { + prepareForTest({ skipSell: true, skipBuy: true }) + + it('reverts', async function () { + const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.user)) + await expectRevert( + validatorUser.unstakeClaimTokensLegacy(), + 'Incomplete withdrawal period' + ) + }) + }) + + describe('new API', function () { + describe('when Alice claims 2 seperate unstakes (1 epoch between unstakes)', function () { + prepareForTest({ skipSell: true }) + + before('sell shares twice', async function () { + this.claimAmount = this.stakeAmount.div(new BN('2')) + + await sellVoucherNewLegacy(this.validatorContract, this.user, this.claimAmount) + await checkPoint([this.validatorUser], this.rootChainOwner, this.stakeManager) + await sellVoucherNewLegacy(this.validatorContract, this.user, this.claimAmount) + }) + + before('checkpoint', async function () { + let currentEpoch = await this.stakeManager.currentEpoch() + let exitEpoch = currentEpoch.add(await this.stakeManager.WITHDRAWAL_DELAY()) + + for (let i = currentEpoch; i <= exitEpoch; i++) { + await checkPoint([this.validatorUser], this.rootChainOwner, this.stakeManager) + } + }) + + it('must claim 1st unstake', async function () { + const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.user)) + this.receipt = await (await validatorUser.unstakeClaimTokens_newLegacy('1')).wait() + }) + + it('must emit DelegatorUnstakeWithId', async function () { + assertInTransaction(this.receipt, EventsHub, 'DelegatorUnstakeWithId', { + validatorId: this.validatorId, + user: this.user, + amount: this.claimAmount.toString(), + nonce: '1' + }) + }) + + it('must claim 2nd unstake', async function () { + const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.user)) + this.receipt = await (await validatorUser.unstakeClaimTokens_newLegacy('2')).wait() + }) + + it('must emit DelegatorUnstakeWithId', async function () { + assertInTransaction(this.receipt, EventsHub, 'DelegatorUnstakeWithId', { + validatorId: this.validatorId, + user: this.user, + amount: this.claimAmount.toString(), + nonce: '2' + }) + }) + + it('must have 0 shares', async function () { + assertBigNumberEquality(await this.validatorContract.balanceOf(this.user), '0') + }) + }) + }) + }) + + describe('getLiquidRewards', function () { + describe('when Alice and Bob buy vouchers (1 checkpoint in-between) and Alice withdraw the rewards', function () { + deployAliceAndBob() + before(async function () { + await buyVoucherLegacy(this.validatorContract, toWei('100'), this.alice) + await checkPoint([this.validatorUser], this.rootChainOwner, this.stakeManager) + await buyVoucherLegacy(this.validatorContract, toWei('4600'), this.bob) + const validatorAlice = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.alice)) + await validatorAlice.withdrawRewardsLegacy() + }) + + it('Bob must call getLiquidRewards', async function () { + await this.validatorContract.getLiquidRewards(this.bob) + }) + }) + }) + + describe('transfer', function () { + describe('when Alice has no rewards', function () { + deployAliceAndBob() + + let initialSharesBalance + + before('Alice purchases voucher', async function () { + await buyVoucherLegacy(this.validatorContract, toWei('100'), this.alice) + initialSharesBalance = await this.validatorContract.balanceOf(this.alice) + }) + + it('must Transfer shares', async function () { + const validatorAlice = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.alice)) + await validatorAlice.transfer(this.bob, initialSharesBalance) + }) + + it('Alice must have 0 shares', async function () { + assertBigNumberEquality(await this.validatorContract.balanceOf(this.alice), '0') + }) + + it("Bob must have Alice's shares", async function () { + assertBigNumberEquality(await this.validatorContract.balanceOf(this.bob), initialSharesBalance) + }) + }) + + describe('when Alice and Bob have unclaimed rewards', function () { + deployAliceAndBob() + + let initialAliceSharesBalance + let initialBobSharesBalance + + let initialAliceMaticBalance + let initialBobMaticBalance + + before('Alice and Bob purchases voucher, checkpoint is commited', async function () { + await buyVoucherLegacy(this.validatorContract, ValidatorDefaultStake, this.alice) + await buyVoucherLegacy(this.validatorContract, ValidatorDefaultStake, this.bob) + + initialAliceSharesBalance = await this.validatorContract.balanceOf(this.alice) + initialBobSharesBalance = await this.validatorContract.balanceOf(this.bob) + + initialAliceMaticBalance = await this.legacyToken.balanceOf(this.alice) + initialBobMaticBalance = await this.legacyToken.balanceOf(this.bob) + + await checkPoint([this.validatorUser], this.rootChainOwner, this.stakeManager) + }) + + it('must Transfer shares', async function () { + const validatorAlice = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.alice)) + this.receipt = await (await validatorAlice.transfer(this.bob, initialAliceSharesBalance)).wait() + }) + + it('must emit DelegatorClaimedRewards for Alice', async function () { + assertInTransaction(this.receipt, StakingInfo, 'DelegatorClaimedRewards', { + validatorId: this.validatorId, + user: this.alice, + rewards: toWei('3000') + }) + }) + + it('Alice must claim 3000 stake', async function () { + assertBigNumberEquality( + await this.stakeToken.balanceOf(this.alice), + toWei('3000') + ) + }) + + it('Alice must have unchanged legacy', async function () { + assertBigNumberEquality( + await this.legacyToken.balanceOf(this.alice), + initialAliceMaticBalance) + }) + + it('Alice must have 0 liquid rewards', async function () { + assertBigNumberEquality(await this.validatorContract.getLiquidRewards(this.alice), '0') + }) + + it('Alice must have 0 shares', async function () { + assertBigNumberEquality(await this.validatorContract.balanceOf(this.alice), '0') + }) + + it("Bob must have Alice's shares", async function () { + assertBigNumberEquality( + await this.validatorContract.balanceOf(this.bob), + initialBobSharesBalance.add(initialAliceSharesBalance) + ) + }) + + it('must emit DelegatorClaimedRewards for Bob', async function () { + assertInTransaction(this.receipt, StakingInfo, 'DelegatorClaimedRewards', { + validatorId: this.validatorId, + user: this.bob, + rewards: toWei('3000') + }) + }) + + it('Bob must claim 3000 stake', async function () { + assertBigNumberEquality( + await this.stakeToken.balanceOf(this.bob), + toWei('3000') + ) + }) + + it('Bob must have unchanged legacy', async function () { + assertBigNumberEquality( + await this.legacyToken.balanceOf(this.bob), + initialBobMaticBalance + ) + }) + + it('Bob must have 0 liquid rewards', async function () { + assertBigNumberEquality(await this.validatorContract.getLiquidRewards(this.bob), '0') + }) + }) + + describe('when transfer to 0x0 address', function () { + deployAliceAndBob() + + let initialAliceSharesBalance + + before('Alice purchases voucher', async function () { + initialAliceSharesBalance = await this.validatorContract.balanceOf(this.alice) + + await buyVoucherLegacy(this.validatorContract, ValidatorDefaultStake, this.alice) + }) + + it('reverts', async function () { + const validatorAlice = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.alice)) + await expectRevert.unspecified( + validatorAlice.transfer(ZeroAddr, initialAliceSharesBalance) + ) + }) + }) + }) +}) + +function shouldHaveCorrectStakes({ user, userTotalStaked, totalStaked }) { + it('must have correct total staked', async function () { + const result = await this.validatorContract.amountStaked(user || this.user) + assertBigNumberEquality(result, userTotalStaked) + }) + + it('validator state must have correct amount', async function () { + assertBigNumberEquality(await this.stakeManager.currentValidatorSetTotalStake(), totalStaked) + }) +} + +function shouldBuyShares({ shares, voucherValueExpected, totalStaked }) { + it('ValidatorShare must mint correct amount of shares', async function () { + assertInTransaction(this.receipt, ValidatorShare, 'Transfer', { + from: ZeroAddr, + to: this.user, + value: shares.toString() + }) + }) + + it('must emit ShareMinted', async function () { + assertInTransaction(this.receipt, StakingInfo, 'ShareMinted', { + validatorId: this.validatorId, + user: this.user, + amount: voucherValueExpected.toString(), + tokens: shares.toString() + }) + }) + + it('must emit StakeUpdate', async function () { + assertInTransaction(this.receipt, StakingInfo, 'StakeUpdate', { + validatorId: this.validatorId, + newAmount: totalStaked.toString() + }) + }) +} + +function shouldWithdrawReward({ initialBalance, validatorId, user, reward, checkBalance = true }) { + if (reward > 0) { + it('must emit Transfer', async function () { + assertInTransaction(this.receipt, TestToken, 'Transfer', { + from: this.stakeManager.address, + to: user || this.user, + value: reward + }) + }) + + it('must emit DelegatorClaimedRewards', async function () { + assertInTransaction(this.receipt, StakingInfo, 'DelegatorClaimedRewards', { + validatorId: validatorId.toString(), + user: user || this.user, + rewards: reward.toString() + }) + }) + } + + if (checkBalance) { + it('must have updated balance', async function () { + const balance = await this.legacyToken.balanceOf(user || this.user) + assertBigNumberEquality(balance, new BN(initialBalance).add(new BN(reward))) + }) + } + + it('must have liquid rewards == 0', async function () { + let rewards = await this.validatorContract.getLiquidRewards(user || this.user) + assertBigNumberEquality('0', rewards) + }) + + it('must have correct initialRewardPerShare', async function () { + const currentRewardPerShare = await this.validatorContract.rewardPerShare() + const userRewardPerShare = await this.validatorContract.initalRewardPerShare(user || this.user) + assertBigNumberEquality(currentRewardPerShare, userRewardPerShare) + }) +} From 13668cfe743bcc2c12bb2a24b8dd3c2d8c90bb96 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Fri, 7 Jun 2024 17:39:36 +0200 Subject: [PATCH 14/92] feat: tests for legacy staking --- .../StakeManager.StakingLegacy.js | 996 ++++++++++++++++++ 1 file changed, 996 insertions(+) create mode 100644 test/units/staking/stakeManager/StakeManager.StakingLegacy.js diff --git a/test/units/staking/stakeManager/StakeManager.StakingLegacy.js b/test/units/staking/stakeManager/StakeManager.StakingLegacy.js new file mode 100644 index 00000000..71c05582 --- /dev/null +++ b/test/units/staking/stakeManager/StakeManager.StakingLegacy.js @@ -0,0 +1,996 @@ +import { StakingInfo, TestToken, Migration, ValidatorShare } from '../../../helpers/artifacts.js' + +import { checkPoint, assertBigNumberEquality, assertBigNumbergt } from '../../../helpers/utils.js' +import testHelpers from '@openzeppelin/test-helpers' +const expectRevert = testHelpers.expectRevert +const BN = testHelpers.BN +import { wallets, walletAmounts, freshDeploy, approveAndStake } from '../deployment.js' +import { assert, expect } from 'chai' +import * as utils from '../../../helpers/utils.js' + +export function doStake( + wallet, + { approveAmount, stakeAmount, noMinting = false, acceptDelegation = false, signer } = {} +) { + return async function () { + let user = wallet.getAddressString() + + let _approveAmount = approveAmount || walletAmounts[user].amount + let _stakeAmount = stakeAmount || walletAmounts[user].stakeAmount + + await approveAndStake.call(this, { + wallet, + stakeAmount: _stakeAmount, + approveAmount: _approveAmount, + acceptDelegation, + noMinting, + signer, + legacy: true + }) + } +} + +export function doUnstake(wallet) { + return async function () { + let user = wallet.getAddressString() + + const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) + + const validatorId = await this.stakeManager.getValidatorId(user) + await stakeManagerUser.unstakeLegacy(validatorId) + } +} + +export function prepareForTest(dynastyValue, validatorThreshold) { + return async function () { + await freshDeploy.call(this) + + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('updateValidatorThreshold', [validatorThreshold]) + ) + + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('updateDynastyValue', [dynastyValue]) + ) + } +} + +describe('migrate matic', function (){ + describe('successful migration', function(){ + const migrationAmount = new BN('100000000000000') + const initalLegacyAmount = new BN('100000000000000') + const initalStakeAmount = new BN(0) + + before('Setup migration scenario', async function() { + await freshDeploy.call(this) + + this.stakeToken = await TestToken.deploy('POL', 'POL') + this.legacyToken = await TestToken.deploy('MATIC', 'MATIC') + + this.migration = await Migration.deploy(this.legacyToken.address, this.stakeToken.address) + + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('setStakingToken', [this.stakeToken.address]) + ) + + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('setLegacyToken', [this.legacyToken.address]) + ) + + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('setMigration', [this.migration.address]) + ) + + await this.stakeToken.mint(this.stakeManager.address, initalStakeAmount.toString()) + await this.legacyToken.mint(this.stakeManager.address, initalLegacyAmount.toString()) + + await this.stakeToken.mint(this.migration.address, web3.utils.toWei('50000000')) + await this.legacyToken.mint(this.migration.address, web3.utils.toWei('50000000')) + }) + + it('must revert with too many token', async function () { + const bigAmount = initalLegacyAmount.mul(new BN('20')) + await expectRevert( this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('convertMaticToPol', [bigAmount.toString()]) + ), 'Update failed') + //'Insufficient MATIC balance' + }) + + it('must migrate', async function () { + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('convertMaticToPol', [migrationAmount.toString()]) + ) + }) + it('must have correct legacy balance', async function(){ + const legacyBalance = await this.legacyToken.balanceOf(this.stakeManager.address) + assertBigNumberEquality(legacyBalance, initalLegacyAmount.sub(migrationAmount)) + }) + + it('must have correct stake balance', async function(){ + const stakeBalance = await this.stakeToken.balanceOf(this.stakeManager.address) + assertBigNumberEquality(stakeBalance, initalStakeAmount.add(migrationAmount)) + }) + }) +}) + + +describe('stake Legacy', function () { + function testStakeRevert(user, userPubkey, amount, stakeAmount, unspecified = false) { + let stakeTokenUser, stakeManagerUser, legacyTokenUser + + before('Approve', async function () { + this.initialBalance = await this.stakeManager.totalStakedFor(user) + + legacyTokenUser = this.legacyToken.connect(this.legacyToken.provider.getSigner(user)) + stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) + + await legacyTokenUser.approve(this.stakeManager.address, new BN(amount).add(this.defaultHeimdallFee).toString()) + }) + + it('must revert', async function () { + if (unspecified) { + await expectRevert( + stakeManagerUser.stakeForLegacy(user, stakeAmount, this.defaultHeimdallFee.toString(), false, userPubkey), + 'no more slots' + ) + } else { + await expectRevert( + stakeManagerUser.stakeForLegacy(user, stakeAmount, this.defaultHeimdallFee.toString(), false, userPubkey), + 'Invalid signer' + ) + } + }) + + it('must have unchanged staked balance', async function () { + const stakedFor = await this.stakeManager.totalStakedFor(user) + assertBigNumberEquality(stakedFor, this.initialBalance) + }) + } + + function testStake(user, userPubkey, amount, stakeAmount, validatorId, fee) { + let stakeTokenUser, stakeManagerUser, legacyTokenUser + before('Approve', async function () { + this.user = user + this.fee = new BN(fee || this.defaultHeimdallFee) + + legacyTokenUser = this.legacyToken.connect(this.legacyToken.provider.getSigner(user)) + stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) + + await legacyTokenUser.approve(this.stakeManager.address, new BN(amount).add(this.fee).toString()) + }) + + it('must stake', async function () { + this.receipt = await ( + await stakeManagerUser.stakeForLegacy(user, stakeAmount.toString(), this.fee.toString(), false, userPubkey) + ).wait() + }) + + it('must emit Staked', async function () { + utils.assertInTransaction(this.receipt, StakingInfo, 'Staked', { + signerPubkey: userPubkey, + signer: user, + amount: stakeAmount + }) + }) + + if (fee) { + it('must emit TopUpFee', async function () { + utils.assertInTransaction(this.receipt, StakingInfo, 'TopUpFee', { + user: user, + fee: this.fee.toString() + }) + }) + } + + it(`must have correct staked amount`, async function () { + const stakedFor = await this.stakeManager.totalStakedFor(user) + assertBigNumberEquality(stakedFor, stakeAmount) + }) + + it('must have correct total staked balance', async function () { + const stake = await this.stakeManager.currentValidatorSetTotalStake() + assertBigNumberEquality(stake, stakeAmount) + }) + + it(`must have validatorId == ${validatorId}`, async function () { + const _validatorId = await this.stakeManager.getValidatorId(user) + _validatorId.toString().should.be.equal(validatorId.toString()) + }) + + it('must have valid validatorId', async function () { + const validatorId = await this.stakeManager.getValidatorId(user) + const value = await this.stakeManager.isValidator(validatorId.toString()) + assert.isTrue(value) + }) + + it('must pay out rewards correctly', async function () { + const validatorId = await this.stakeManager.getValidatorId(user) + const reward = await this.stakeManager.validatorReward(validatorId) + const balanceBefore = await this.legacyToken.balanceOf(user) + assertBigNumberEquality(reward, new BN(0)) + + await checkPoint(wallets, this.rootChainOwner, this.stakeManager) + await checkPoint(wallets, this.rootChainOwner, this.stakeManager) + const newReward = await this.stakeManager.validatorReward(validatorId) + assertBigNumbergt(newReward, reward) + await stakeManagerUser.withdrawRewardsLegacy(validatorId) + const balanceAfter = await this.legacyToken.balanceOf(user) + assertBigNumberEquality(balanceAfter.sub(balanceBefore), newReward) + + await checkPoint(wallets, this.rootChainOwner, this.stakeManager) + await checkPoint(wallets, this.rootChainOwner, this.stakeManager) + const newReward2 = await this.stakeManager.validatorReward(validatorId) + await stakeManagerUser.withdrawRewardsLegacy(validatorId) + const balanceAfter2 = await this.legacyToken.balanceOf(user) + assertBigNumberEquality(balanceAfter2.sub(balanceAfter), newReward2) + assertBigNumberEquality(newReward2, newReward) + }) + } + + function testRestake(user, amount, stakeAmount, restakeAmount, totalStaked) { + let stakeTokenUser, stakeManagerUser, legacyTokenUser + + before('Approve', async function () { + this.user = user + legacyTokenUser = this.legacyToken.connect(this.legacyToken.provider.getSigner(user)) + stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) + + await legacyTokenUser.approve(this.stakeManager.address, amount.toString()) + }) + + it('must restake', async function () { + const validatorId = await this.stakeManager.getValidatorId(this.user) + this.receipt = await (await stakeManagerUser.restakeLegacy(validatorId, restakeAmount, false)).wait() + }) + + it('must emit StakeUpdate', async function () { + const validatorId = await this.stakeManager.getValidatorId(this.user) + await utils.assertInTransaction(this.receipt, StakingInfo, 'StakeUpdate', { + validatorId: validatorId.toString() + }) + }) + + it('must emit Restaked', async function () { + const validatorId = await this.stakeManager.getValidatorId(this.user) + await utils.assertInTransaction(this.receipt, StakingInfo, 'Restaked', { + validatorId, + amount: stakeAmount.toString(), + total: totalStaked.toString() + }) + }) + + it(`must have correct total staked amount`, async function () { + const stakedFor = await this.stakeManager.totalStakedFor(user) + assertBigNumberEquality(stakedFor, stakeAmount) + }) + } + + describe('double stake', async function () { + before(freshDeploy) + + describe('when stakes first time', function () { + const amounts = walletAmounts[wallets[1].getAddressString()] + testStake( + wallets[1].getChecksumAddressString(), + wallets[1].getPublicKeyString(), + amounts.amount, + amounts.stakeAmount, + 1 + ) + }) + + describe('when stakes again', function () { + testStakeRevert( + wallets[1].getChecksumAddressString(), + wallets[1].getPublicKeyString(), + web3.utils.toWei('200'), + web3.utils.toWei('200') + ) + }) + }) + + describe('stake and restake following by another stake', function () { + before(freshDeploy) + + const amounts = walletAmounts[wallets[2].getAddressString()] + before('Stake', doStake(wallets[2])) + + describe('when restakes', function () { + testRestake( + wallets[2].getChecksumAddressString(), + amounts.restakeAmonut, + amounts.amount, + amounts.restakeAmonut, + amounts.amount + ) + }) + + describe('when stakes again', function () { + testStakeRevert( + wallets[2].getChecksumAddressString(), + wallets[2].getPublicKeyString(), + web3.utils.toWei('250'), + web3.utils.toWei('150') + ) + }) + describe('when reStakes while on going auction', function () { + it('when auction is active', async function () { + let auctionBid = web3.utils.toWei('10000') + const auctionUser = wallets[4].getAddressString() + await this.stakeToken.mint(auctionUser, auctionBid) + + const stakeTokenUser = this.stakeToken.connect(this.stakeToken.provider.getSigner(auctionUser)) + const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(auctionUser)) + + await stakeTokenUser.approve(this.stakeManager.address, auctionBid) + const validatorId = await this.stakeManager.getValidatorId(wallets[2].getChecksumAddressString()) + await stakeManagerUser.startAuction(validatorId, auctionBid, false, auctionUser) + testRestake( + wallets[2].getChecksumAddressString(), + amounts.restakeAmonut, + amounts.amount, + amounts.restakeAmonut, + amounts.amount + ) + }) + }) + }) + + describe('stake beyond validator threshold', async function () { + before(prepareForTest(2, 1)) + + describe('when user stakes', function () { + const amounts = walletAmounts[wallets[3].getAddressString()] + testStake( + wallets[3].getChecksumAddressString(), + wallets[3].getPublicKeyString(), + amounts.amount, + amounts.stakeAmount, + 1 + ) + }) + + describe('when other user stakes beyond validator threshold', function () { + testStakeRevert( + wallets[4].getChecksumAddressString(), + wallets[4].getPublicKeyString(), + web3.utils.toWei('100'), + web3.utils.toWei('100'), + true + ) + }) + }) + + describe('consecutive stakes', function () { + before(freshDeploy) + + it('validatorId must increment 1 by 1', async function () { + const _wallets = [wallets[1], wallets[2], wallets[3]] + let expectedValidatorId = 1 + for (const wallet of _wallets) { + await doStake(wallet, { approveAmount: web3.utils.toWei('100'), stakeAmount: web3.utils.toWei('100') }).call( + this + ) + + const validatorId = await this.stakeManager.getValidatorId(wallet.getAddressString()) + assertBigNumberEquality(expectedValidatorId, validatorId) + expectedValidatorId++ + } + }) + }) + + describe('stake with heimdall fee', function () { + before(freshDeploy) + + testStake( + wallets[0].getChecksumAddressString(), + wallets[0].getPublicKeyString(), + web3.utils.toWei('200'), + web3.utils.toWei('150'), + 1, + web3.utils.toWei('50') + ) + }) + + describe('when Alice stakes, change signer and stakes with old signer', function () { + const AliceWallet = wallets[1] + const newSigner = wallets[2].getPublicKeyString() + + before(freshDeploy) + before(doStake(AliceWallet)) + before('Change signer', async function () { + const signerUpdateLimit = await this.stakeManager.signerUpdateLimit() + await this.stakeManager.advanceEpoch(signerUpdateLimit) + + this.validatorId = await this.stakeManager.getValidatorId(AliceWallet.getAddressString()) + + const stakeManagerAlice = this.stakeManager.connect( + this.stakeManager.provider.getSigner(AliceWallet.getAddressString()) + ) + await stakeManagerAlice.updateSigner(this.validatorId, newSigner) + }) + + it('reverts', async function () { + await expectRevert(doStake(wallets[3], { signer: AliceWallet.getPublicKeyString() }).call(this), 'Invalid signer') + }) + }) +}) + +describe('unstake Legacy', function () { + describe('when Alice unstakes and update the signer', function () { + const AliceWallet = wallets[1] + const BobWallet = wallets[3] + const AliceNewWallet = wallets[2] + let stakeManagerAlice + + before(freshDeploy) + before(doStake(AliceWallet)) + before(doStake(BobWallet)) + before('Change signer', async function () { + const signerUpdateLimit = await this.stakeManager.signerUpdateLimit() + await this.stakeManager.advanceEpoch(signerUpdateLimit) + + this.validatorId = await this.stakeManager.getValidatorId(AliceWallet.getAddressString()) + + stakeManagerAlice = this.stakeManager.connect( + this.stakeManager.provider.getSigner(AliceWallet.getAddressString()) + ) + }) + + it('Alice should unstake', async function () { + this.receipt = await stakeManagerAlice.unstakeLegacy(this.validatorId) + }) + + it("Signers list should have only Bob's signer", async function () { + assert((await this.stakeManager.signers(0)) == BobWallet.getChecksumAddressString(), 'no Bob signer!') + await expect(this.stakeManager.signers(1)) + }) + + it('Alice should update signer', async function () { + await stakeManagerAlice.updateSigner(this.validatorId, AliceNewWallet.getPublicKeyString()) + }) + + it("Signers list should haveonly Bob's signer", async function () { + assert((await this.stakeManager.signers(0)) == BobWallet.getChecksumAddressString(), 'no Bob signer!') + await expect(this.stakeManager.signers(1)) + }) + }) + + describe('when user unstakes right after stake', async function () { + const user = wallets[2].getChecksumAddressString() + const amounts = walletAmounts[wallets[2].getAddressString()] + let stakeManagerUser + + before('Fresh deploy', prepareForTest(2, 3)) + before(doStake(wallets[2])) + before(async function () { + this.validatorId = await this.stakeManager.getValidatorId(user) + + const reward = await this.stakeManager.validatorReward(this.validatorId) + this.reward = reward + this.afterStakeBalance = await this.legacyToken.balanceOf(user) + + stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) + }) + + it('must unstake', async function () { + this.receipt = await (await stakeManagerUser.unstakeLegacy(this.validatorId)).wait() + }) + + it('must emit UnstakeInit', async function () { + await utils.assertInTransaction(this.receipt, StakingInfo, 'UnstakeInit', { + amount: amounts.stakeAmount, + validatorId: this.validatorId, + user + }) + }) + + it('must emit ClaimRewards', async function () { + await utils.assertInTransaction(this.receipt, StakingInfo, 'ClaimRewards', { + validatorId: this.validatorId, + amount: '0', + totalAmount: '0' + }) + }) + + it('must emit Transfer', async function () { + await utils.assertInTransaction(this.receipt, TestToken, 'Transfer', { + value: this.reward, + to: user + }) + }) + + it('must have increased balance by reward', async function () { + const balance = await this.legacyToken.balanceOf(user) + assertBigNumberEquality(balance, this.afterStakeBalance.add(this.reward)) + }) + }) + + describe('when user unstakes after 2 epochs', async function () { + before('Fresh deploy', prepareForTest(2, 3)) + + const user = wallets[3].getChecksumAddressString() + const amounts = walletAmounts[wallets[3].getAddressString()] + const w = [wallets[2], wallets[3]] + let stakeManagerUser + + before(doStake(wallets[2])) + before(doStake(wallets[3], { acceptDelegation: true })) + before(async function () { + this.validatorId = await this.stakeManager.getValidatorId(user) + + const legacyToken4 = this.legacyToken.connect(this.legacyToken.provider.getSigner(wallets[4].getAddressString())) + stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) + + // delegate tokens to validator + const validatorShareAddr = await this.stakeManager.getValidatorContract(this.validatorId) + await legacyToken4.approve(this.stakeManager.address, web3.utils.toWei('100')) + const validator = await ValidatorShare.attach(validatorShareAddr) + const validator4 = validator.connect(validator.provider.getSigner(wallets[4].getAddressString())) + await validator4.buyVoucherLegacy(web3.utils.toWei('100'), 0) + + this.afterStakeBalance = await this.legacyToken.balanceOf(user) + }) + + before(async function () { + await checkPoint(w, this.rootChainOwner, this.stakeManager) + await checkPoint(w, this.rootChainOwner, this.stakeManager) + + this.reward = await this.stakeManager.validatorReward(this.validatorId) + this.delegatorReward = await this.stakeManager.delegatorsReward(this.validatorId) + }) + + it('must unstake', async function () { + const validatorId = await this.stakeManager.getValidatorId(user) + this.receipt = await (await stakeManagerUser.unstakeLegacy(validatorId)).wait() + }) + + it('must emit UnstakeInit', async function () { + const validatorId = await this.stakeManager.getValidatorId(user) + await utils.assertInTransaction(this.receipt, StakingInfo, 'UnstakeInit', { + amount: amounts.amount, + validatorId, + user + }) + }) + + it('must emit ClaimRewards', async function () { + await utils.assertInTransaction(this.receipt, StakingInfo, 'ClaimRewards', { + validatorId: this.validatorId, + amount: this.reward, + totalAmount: this.reward + }) + }) + + it('must emit Transfer', async function () { + await utils.assertInTransaction(this.receipt, TestToken, 'Transfer', { + value: this.reward, + to: user + }) + }) + + it('must have increased balance by reward', async function () { + const balance = await this.legacyToken.balanceOf(user) + assertBigNumberEquality(balance, this.afterStakeBalance.add(this.reward)) + }) + + it('should not distribute additional staking or delegation rewards after unstaking', async function () { + const validatorId = await this.stakeManager.getValidatorId(user) + + let validatorRewardsBefore = await this.stakeManager.validatorReward(validatorId) + let delegationRewardsBefore = await this.stakeManager.delegatorsReward(validatorId) + assertBigNumberEquality(delegationRewardsBefore, this.delegatorReward) + + // complete unstake and remove validator + await checkPoint(w, this.rootChainOwner, this.stakeManager) + + let validatorRewardsAfter = await this.stakeManager.validatorReward(validatorId) + let delegationRewardsAfter = await this.stakeManager.delegatorsReward(validatorId) + + assertBigNumbergt(validatorRewardsAfter, validatorRewardsBefore) + assertBigNumbergt(delegationRewardsAfter, delegationRewardsBefore) + + await stakeManagerUser.withdrawRewardsLegacy(validatorId) + const balanceBefore = await this.legacyToken.balanceOf(user) + + await checkPoint([wallets[2]], this.rootChainOwner, this.stakeManager) + + await stakeManagerUser.withdrawRewardsLegacy(validatorId) + assertBigNumberEquality(await this.legacyToken.balanceOf(user), balanceBefore) + + assertBigNumberEquality(await this.stakeManager.validatorReward(validatorId), new BN(0)) + assertBigNumberEquality(await this.stakeManager.delegatorsReward(validatorId), delegationRewardsAfter) + }) + }) + + describe('reverts', function () { + beforeEach('Fresh Deploy', freshDeploy) + const user = wallets[2].getChecksumAddressString() + let stakeManagerUser + + beforeEach(doStake(wallets[2])) + + it('when validatorId is invalid', async function () { + stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) + + await expectRevert.unspecified(stakeManagerUser.unstakeLegacy('999999')) + }) + + it('when user is not staker', async function () { + const validatorId = await this.stakeManager.getValidatorId(user) + const stakeManager3 = this.stakeManager.connect(this.stakeManager.provider.getSigner(3)) + + await expectRevert.unspecified(stakeManager3.unstakeLegacy(validatorId)) + }) + + it('when unstakes 2 times', async function () { + const validatorId = await this.stakeManager.getValidatorId(user) + await stakeManagerUser.unstakeLegacy(validatorId) + + await expectRevert.unspecified(stakeManagerUser.unstakeLegacy(validatorId)) + }) + + it('when unstakes during auction', async function () { + const amount = web3.utils.toWei('1200').toString() + const auctionUser = wallets[4].getAddressString() + await this.stakeToken.mint(auctionUser, amount) + + const stakeTokenAuctionUser = this.stakeToken.connect(this.stakeToken.provider.getSigner(auctionUser)) + const stakeManagerAuctionUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(auctionUser)) + + await stakeTokenAuctionUser.approve(this.stakeManager.address, amount) + const validatorId = await this.stakeManager.getValidatorId(user) + await stakeManagerAuctionUser.startAuction(validatorId, amount, false, wallets[4].getPublicKeyString()) + await expectRevert.unspecified(stakeManagerUser.unstakeLegacy(validatorId)) + }) + }) +}) + +describe('unstakeClaim Legacy', function () { + describe('when user claims right after stake', function () { + before('Fresh Deploy', prepareForTest(1, 10)) + before('Stake', doStake(wallets[2])) + before('Unstake', doUnstake(wallets[2])) + + const user = wallets[2].getAddressString() + + it('must revert', async function () { + const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) + const ValidatorId = await this.stakeManager.getValidatorId(user) + await expect(stakeManagerUser.unstakeClaimLegacy(ValidatorId)) + }) + }) + + describe('when user claims after 1 epoch and 1 dynasty passed', function () { + let dynasties = 1 + const Alice = wallets[2].getChecksumAddressString() + let stakeManagerAlice + + before('Fresh Deploy', prepareForTest(dynasties, 10)) + before('Alice Stake', doStake(wallets[2])) + before('Bob Stake', doStake(wallets[3])) + before('Alice Unstake', doUnstake(wallets[2])) + + before('Checkpoint', async function () { + this.validatorId = await this.stakeManager.getValidatorId(Alice) + this.aliceStakeAmount = await this.stakeManager.validatorStake(this.validatorId) + stakeManagerAlice = this.stakeManager.connect(this.stakeManager.provider.getSigner(Alice)) + + await checkPoint([wallets[3], wallets[2]], this.rootChainOwner, this.stakeManager) + + while (dynasties-- > 0) { + await checkPoint([wallets[3]], this.rootChainOwner, this.stakeManager) + } + }) + + it('must claim', async function () { + this.receipt = await (await stakeManagerAlice.unstakeClaimLegacy(this.validatorId)).wait() + }) + + it('must emit Unstaked', async function () { + const stake = await this.stakeManager.currentValidatorSetTotalStake() + await utils.assertInTransaction(this.receipt, StakingInfo, 'Unstaked', { + user: Alice, + validatorId: this.validatorId, + amount: this.aliceStakeAmount, + total: stake + }) + }) + + it('must have correct staked balance', async function () { + const stake = await this.stakeManager.currentValidatorSetTotalStake() + assertBigNumberEquality(stake, walletAmounts[wallets[3].getAddressString()].stakeAmount) + }) + }) + + describe('when user claims next epoch', function () { + before('Fresh Deploy', prepareForTest(1, 10)) + + before('Alice Stake', doStake(wallets[2])) + before('Bob Stake', doStake(wallets[3])) + + before('Alice Unstake', doUnstake(wallets[2])) + + let user + + before('Checkpoint', async function () { + await checkPoint([wallets[3], wallets[2]], this.rootChainOwner, this.stakeManager) + user = wallets[2].getAddressString() + }) + + it('must revert', async function () { + const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) + const validatorId = await this.stakeManager.getValidatorId(user) + await expect(stakeManagerUser.unstakeClaimLegacy(validatorId)) + }) + }) + + describe('when user claims before 1 dynasty passed', function () { + before('Fresh Deploy', prepareForTest(2, 10)) + + before('Alice Stake', doStake(wallets[2])) + before('Bob Stake', doStake(wallets[3])) + + before('Alice Unstake', doUnstake(wallets[2])) + + let user + + before('Checkpoint', async function () { + await checkPoint([wallets[3], wallets[2]], this.rootChainOwner, this.stakeManager) + user = wallets[2].getAddressString() + }) + + it('must revert', async function () { + const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) + const validatorId = await this.stakeManager.getValidatorId(user) + await expect(stakeManagerUser.unstakeClaimLegacy(validatorId)) + }) + }) + + describe('when Alice, Bob and Eve stake, but Alice and Bob claim after 1 epoch and 1 dynasty passed', function () { + before(prepareForTest(1, 10)) + + const Alice = wallets[2] + const Bob = wallets[3] + const Eve = wallets[4] + const stakeAmount = web3.utils.toWei('100') + + before('Alice stake', doStake(Alice, { noMinting: true, stakeAmount })) + before('Bob stake', doStake(Bob, { noMinting: true, stakeAmount })) + before('Eve stake', doStake(Eve, { noMinting: true, stakeAmount })) + + before('Alice unstake', doUnstake(Alice)) + before('Bob unstake', doUnstake(Bob)) + + before('Checkpoint', async function () { + await checkPoint([Eve, Bob, Alice], this.rootChainOwner, this.stakeManager) + await checkPoint([Eve], this.rootChainOwner, this.stakeManager) + }) + + describe('when Alice claims', function () { + const user = Alice.getAddressString() + + it('must claim', async function () { + const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) + this.validatorId = await this.stakeManager.getValidatorId(user) + this.reward = await this.stakeManager.validatorReward(this.validatorId) + this.receipt = await (await stakeManagerUser.unstakeClaimLegacy(this.validatorId)).wait() + }) + + it('must have correct reward', async function () { + assertBigNumberEquality(this.reward, web3.utils.toWei('3000')) + }) + + it('must emit ClaimRewards', async function () { + await utils.assertInTransaction(this.receipt, StakingInfo, 'ClaimRewards', { + validatorId: this.validatorId, + amount: web3.utils.toWei('3000'), + totalAmount: await this.stakeManager.totalRewardsLiquidated() + }) + }) + + it('must have pre-stake + reward - heimdall fee balance', async function () { + let balance = await this.legacyToken.balanceOf(user) + assertBigNumberEquality( + balance, + new BN(walletAmounts[user].initialBalance).add(new BN(this.reward.toString())).sub(this.defaultHeimdallFee) + ) + }) + }) + + describe('when Bob claims', function () { + const user = Bob.getAddressString() + + it('must claim', async function () { + const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) + this.validatorId = await this.stakeManager.getValidatorId(user) + this.reward = await this.stakeManager.validatorReward(this.validatorId) + this.receipt = await (await stakeManagerUser.unstakeClaimLegacy(this.validatorId)).wait() + }) + + it('must have correct reward', async function () { + assertBigNumberEquality(this.reward, web3.utils.toWei('3000')) + }) + + it('must emit ClaimRewards', async function () { + await utils.assertInTransaction(this.receipt, StakingInfo, 'ClaimRewards', { + validatorId: this.validatorId, + amount: web3.utils.toWei('3000'), + totalAmount: await this.stakeManager.totalRewardsLiquidated() + }) + }) + + it('must have pre-stake + reward - heimdall fee balance', async function () { + let balance = await this.legacyToken.balanceOf(user) + assertBigNumberEquality( + balance, + new BN(walletAmounts[user].initialBalance).add(new BN(this.reward.toString())).sub(this.defaultHeimdallFee) + ) + }) + }) + + describe('afterwards verification', function () { + it('must have corect number of validators', async function () { + const validatorCount = await this.stakeManager.currentValidatorSetSize() + assertBigNumberEquality(validatorCount, '1') + }) + + it('staked balance must have only Eve balance', async function () { + const stake = await this.stakeManager.currentValidatorSetTotalStake() + assertBigNumberEquality(stake, stakeAmount) + }) + + it('Eve must have correct rewards', async function () { + const validatorId = await this.stakeManager.getValidatorId(Eve.getAddressString()) + this.reward = await this.stakeManager.validatorReward(validatorId) + assertBigNumberEquality(this.reward, web3.utils.toWei('12000')) + }) + }) + }) +}) + +describe('restake Legacy', function () { + const initialStake = web3.utils.toWei('1000') + const initialStakers = [wallets[0], wallets[1]] + + function doDeploy(acceptDelegation) { + return async function () { + await prepareForTest(8, 8).call(this) + + const checkpointReward = new BN(web3.utils.toWei('10000')) + + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('updateCheckpointReward', [checkpointReward.toString()]) + ) + + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('updateCheckPointBlockInterval', [1]) + ) + + const proposerBonus = 10 + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('updateProposerBonus', [proposerBonus]) + ) + + for (const wallet of initialStakers) { + await approveAndStake.call(this, { wallet, stakeAmount: initialStake, acceptDelegation, legacy: true }) + } + + // cooldown period + let auctionPeriod = (await this.stakeManager.auctionPeriod()).toNumber() + let currentEpoch = (await this.stakeManager.currentEpoch()).toNumber() + + for (let i = currentEpoch; i <= auctionPeriod; i++) { + await checkPoint(initialStakers, this.rootChainOwner, this.stakeManager) + } + // without 10% proposer bonus + this.validatorReward = checkpointReward + .mul(new BN(100 - proposerBonus)) + .div(new BN(100)) + .mul(new BN(auctionPeriod - currentEpoch)) + this.validatorId = '1' + this.user = initialStakers[0].getAddressString() + this.amount = web3.utils.toWei('100') + + await this.legacyToken.mint(this.user, this.amount) + this.legacyTokenUser = this.legacyToken.connect(this.stakeToken.provider.getSigner(this.user)) + await this.legacyTokenUser.approve(this.stakeManager.address, this.amount) + } + } + + function testRestake(withDelegation, withRewards) { + before(doDeploy(withDelegation)) + + before(async function () { + this.oldTotalStaked = await this.stakeManager.totalStaked() + this.validatorOldState = await this.stakeManager.validators(this.validatorId) + + if (!withRewards) { + this.validatorReward = new BN(0) + this.oldReward = await this.stakeManager.validatorReward(this.validatorId) + } + }) + + it('must restake rewards', async function () { + const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(this.user)) + + this.receipt = await (await stakeManagerUser.restakeLegacy(this.validatorId, this.amount, withRewards)).wait() + }) + + it('must emit StakeUpdate', async function () { + await utils.assertInTransaction(this.receipt, StakingInfo, 'StakeUpdate', { + validatorId: this.validatorId, + newAmount: this.validatorOldState.amount.add(this.amount.toString()).add(this.validatorReward.toString()) + }) + }) + + it('must emit Restaked', async function () { + await utils.assertInTransaction(this.receipt, StakingInfo, 'Restaked', { + validatorId: this.validatorId, + amount: this.validatorOldState.amount.add(this.amount.toString()).add(this.validatorReward.toString()), + total: this.oldTotalStaked.add(this.amount.toString()).add(this.validatorReward.toString()) + }) + }) + + if (withRewards) { + it('validator rewards must be 0', async function () { + const reward = await this.stakeManager.validatorReward(this.validatorId) + + assertBigNumberEquality(reward, 0) + }) + } else { + it('validator rewards must be untouched', async function () { + const reward = await this.stakeManager.validatorReward(this.validatorId) + + assertBigNumberEquality(reward, this.oldReward) + }) + } + } + + describe('with delegation', function () { + describe('with rewards', function () { + testRestake(true, true) + }) + + describe('without rewards', function () { + testRestake(true, false) + }) + }) + + describe('without delegation', function () { + describe('with rewards', function () { + testRestake(false, true) + }) + + describe('without rewards', function () { + testRestake(false, false) + }) + }) + + describe('reverts', function () { + before(doDeploy(false)) + + before(() => {}) + + it('when validatorId is incorrect', async function () { + const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(this.user)) + await expect(stakeManagerUser.restakeLegacy('0', this.amount, false)) + }) + + it('when restake after unstake during same epoch', async function () { + await this.stakeManager.unstakeLegacy(this.validatorId) + const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(this.user)) + await expectRevert(stakeManagerUser.restakeLegacy(this.validatorId, this.amount, false), 'No restaking') + }) + }) +}) From 499d8871eddb3aa0c03c6633f943b59af987bce3 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Fri, 7 Jun 2024 22:44:40 +0200 Subject: [PATCH 15/92] fix: move storage to prevent conflicts --- contracts/staking/stakeManager/StakeManagerStorage.sol | 4 ---- .../staking/stakeManager/StakeManagerStorageExtension.sol | 3 +++ 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/contracts/staking/stakeManager/StakeManagerStorage.sol b/contracts/staking/stakeManager/StakeManagerStorage.sol index 2bd42f42..69548626 100644 --- a/contracts/staking/stakeManager/StakeManagerStorage.sol +++ b/contracts/staking/stakeManager/StakeManagerStorage.sol @@ -94,8 +94,4 @@ contract StakeManagerStorage is GovernanceLockable, RootChainable { mapping(uint256 => uint256) public latestSignerUpdateEpoch; uint256 public totalHeimdallFee; - - // @note does this conflict with StakeManagerStorageExtension? - IERC20 public tokenLegacy; // TODO Set MATIC and POL on reinitialization (setStakingToken). - IPolygonMigration public migration; } diff --git a/contracts/staking/stakeManager/StakeManagerStorageExtension.sol b/contracts/staking/stakeManager/StakeManagerStorageExtension.sol index dca5cd23..4b9bf515 100644 --- a/contracts/staking/stakeManager/StakeManagerStorageExtension.sol +++ b/contracts/staking/stakeManager/StakeManagerStorageExtension.sol @@ -14,4 +14,7 @@ contract StakeManagerStorageExtension { uint256 public maxRewardedCheckpoints; // increase / decrease value for faster or slower checkpoints, 0 - 100% uint256 public checkpointRewardDelta; + + IERC20 public tokenLegacy; + IPolygonMigration public migration; } From 49e288fb102d5cd64af01b8d2ea21d12272c105b Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Sat, 8 Jun 2024 23:06:04 +0200 Subject: [PATCH 16/92] fix: remove unused function --- .../staking/validatorShare/ValidatorShare.sol | 24 ++++++------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/contracts/staking/validatorShare/ValidatorShare.sol b/contracts/staking/validatorShare/ValidatorShare.sol index b4d56f86..95ae7536 100644 --- a/contracts/staking/validatorShare/ValidatorShare.sol +++ b/contracts/staking/validatorShare/ValidatorShare.sol @@ -215,17 +215,12 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I // @note migrateOut function migrateOut(address user, uint256 amount) external onlyOwner { - _migrateOut(user, amount, false); + _migrateOut(user, amount); } // @note - function migrateOutLegacy(address user, uint256 amount) external onlyOwner { - _migrateOut(user, amount, true); - } - - // @note - function _migrateOut(address user, uint256 amount, bool legacy) internal { - _withdrawAndTransferReward(user, legacy); + function _migrateOut(address user, uint256 amount) internal { + _withdrawAndTransferReward(user, false); (uint256 totalStaked, uint256 rate) = getTotalStake(user); require(totalStaked >= amount, "Migrating too much"); @@ -243,17 +238,12 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I // @note migrateIn function migrateIn(address user, uint256 amount) external onlyOwner { - _migrateIn(user, amount, false); - } - - // @note - function migrateInLegacy(address user, uint256 amount) external onlyOwner { - _migrateIn(user, amount, true); - } + _migrateIn(user, amount); + } // @note - function _migrateIn(address user, uint256 amount, bool legacy) internal { - _withdrawAndTransferReward(user, legacy); + function _migrateIn(address user, uint256 amount) internal { + _withdrawAndTransferReward(user, false); _buyShares(amount, 0, user); } From b5558ed68c290ed12e488cb343beed5d522b976f Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Sat, 8 Jun 2024 23:06:29 +0200 Subject: [PATCH 17/92] fix: move imports --- contracts/staking/stakeManager/StakeManagerStorage.sol | 1 - .../staking/stakeManager/StakeManagerStorageExtension.sol | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/contracts/staking/stakeManager/StakeManagerStorage.sol b/contracts/staking/stakeManager/StakeManagerStorage.sol index 69548626..6b448a83 100644 --- a/contracts/staking/stakeManager/StakeManagerStorage.sol +++ b/contracts/staking/stakeManager/StakeManagerStorage.sol @@ -8,7 +8,6 @@ import {RootChainable} from "../../common/mixin/RootChainable.sol"; import {StakingInfo} from "../StakingInfo.sol"; import {StakingNFT} from "./StakingNFT.sol"; import {ValidatorShareFactory} from "../validatorShare/ValidatorShareFactory.sol"; -import {IPolygonMigration} from "../../common/misc/IPolygonMigration.sol"; contract StakeManagerStorage is GovernanceLockable, RootChainable { enum Status {Inactive, Active, Locked, Unstaked} diff --git a/contracts/staking/stakeManager/StakeManagerStorageExtension.sol b/contracts/staking/stakeManager/StakeManagerStorageExtension.sol index 4b9bf515..68e715a8 100644 --- a/contracts/staking/stakeManager/StakeManagerStorageExtension.sol +++ b/contracts/staking/stakeManager/StakeManagerStorageExtension.sol @@ -1,5 +1,8 @@ pragma solidity 0.5.17; +import {IPolygonMigration} from "../../common/misc/IPolygonMigration.sol"; +import {IERC20} from "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol"; + contract StakeManagerStorageExtension { address public eventsHub; uint256 public rewardPerStake; From 21f849ec6b800575cb81e1803d3f9b5d63f915f5 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Mon, 10 Jun 2024 11:22:04 +0200 Subject: [PATCH 18/92] feat: allow legacy config in test deployments --- test/helpers/deployer.js | 36 ++++++++++++++++++++++---------- test/units/staking/deployment.js | 21 +++++++++++++------ 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/test/helpers/deployer.js b/test/helpers/deployer.js index 823f76b8..edf7adbb 100644 --- a/test/helpers/deployer.js +++ b/test/helpers/deployer.js @@ -17,16 +17,23 @@ class Deployer { return contractFactories.EventsHub.attach(proxy.address) } - async freshDeploy(owner) { + async freshDeploy(owner, legacy = false) { this.governance = await this.deployGovernance() this.registry = await contractFactories.Registry.deploy(this.governance.address) this.eventsHub = await this.deployEventsHub(this.registry.address) this.validatorShareFactory = await contractFactories.ValidatorShareFactory.deploy() this.stakeToken = await contractFactories.TestToken.deploy('Stake Token', 'ST') - this.legacyToken = await contractFactories.TestToken.deploy('Legacy Token', 'LT') - this.migration = await contractFactories.Migration.deploy(this.legacyToken.address, this.stakeToken.address) - + if (legacy){ + this.legacyToken = await contractFactories.TestToken.deploy('Legacy Token', 'LT') + this.migration = await contractFactories.Migration.deploy(this.legacyToken.address, this.stakeToken.address) + } else { + this.legacyToken = {} + this.migration = {} + this.legacyToken.address = '0x0000000000000000000000000000000000000000' + this.migration.address = '0x0000000000000000000000000000000000000000' + } + this.stakingInfo = await contractFactories.StakingInfo.deploy(this.registry.address) this.slashingManager = await contractFactories.SlashingManager.deploy( this.registry.address, @@ -88,7 +95,7 @@ class Deployer { return _contracts } - async deployStakeManager(wallets) { + async deployStakeManager(wallets, legacy = false) { this.governance = await this.deployGovernance() this.registry = await contractFactories.Registry.deploy(this.governance.address) @@ -98,12 +105,19 @@ class Deployer { this.rootChain = await this.deployRootChain() this.stakingInfo = await contractFactories.StakingInfo.deploy(this.registry.address) this.stakeToken = await contractFactories.TestToken.deploy('Stake Token', 'STAKE') - this.legacyToken = await contractFactories.TestToken.deploy('Legacy Token', 'LT') - this.migration = await contractFactories.Migration.deploy(this.legacyToken.address, this.stakeToken.address) - - // Mint token into migration, so we can actually migrate - await this.stakeToken.mint(this.migration.address, web3.utils.toWei('1000000')) - await this.legacyToken.mint(this.migration.address, web3.utils.toWei('1000000')) + + if (legacy) { + this.legacyToken = await contractFactories.TestToken.deploy('Legacy Token', 'LT') + this.migration = await contractFactories.Migration.deploy(this.legacyToken.address, this.stakeToken.address) + // Mint token into migration, so we can actually migrate + await this.stakeToken.mint(this.migration.address, web3.utils.toWei('1000000')) + await this.legacyToken.mint(this.migration.address, web3.utils.toWei('1000000')) + } else { + this.legacyToken = {} + this.migration = {} + this.legacyToken.address = '0x0000000000000000000000000000000000000000' + this.migration.address = '0x0000000000000000000000000000000000000000' + } this.stakingNFT = await contractFactories.StakingNFT.deploy('Matic Validator', 'MV') diff --git a/test/units/staking/deployment.js b/test/units/staking/deployment.js index 44de9044..2a56096e 100644 --- a/test/units/staking/deployment.js +++ b/test/units/staking/deployment.js @@ -34,10 +34,9 @@ export const walletAmounts = { } } -export async function freshDeploy() { - let contracts = await deployer.deployStakeManager(wallets) +export async function freshDeploy(legacy = false) { + let contracts = await deployer.deployStakeManager(wallets, legacy) this.stakeToken = contracts.stakeToken - this.legacyToken = contracts.legacyToken this.stakeManager = contracts.stakeManager this.nftContract = contracts.stakingNFT this.rootChainOwner = contracts.rootChainOwner @@ -45,7 +44,13 @@ export async function freshDeploy() { this.governance = contracts.governance this.validatorShare = deployer.validatorShare this.slashingManager = contracts.slashingManager - this.migration = contracts.migration + if (legacy) { + this.legacyToken = contracts.legacyToken + this.migration = contracts.migration + } else { + this.legacyToken = {} + this.migration = {} + } await this.governance.update( this.stakeManager.address, @@ -57,12 +62,16 @@ export async function freshDeploy() { ) for (const walletAddr in walletAmounts) { - await this.legacyToken.mint(walletAddr, walletAmounts[walletAddr].initialBalance) + if (legacy) { + await this.legacyToken.mint(walletAddr, walletAmounts[walletAddr].initialBalance) + } await this.stakeToken.mint(walletAddr, walletAmounts[walletAddr].initialBalance) } await this.stakeToken.mint(this.stakeManager.address, web3.utils.toWei('10000000')) - await this.legacyToken.mint(this.stakeManager.address, web3.utils.toWei('20000000')) + if (legacy) { + await this.legacyToken.mint(this.stakeManager.address, web3.utils.toWei('20000000')) + } this.defaultHeimdallFee = new BN(web3.utils.toWei('1')) } From 8d64c6e038ce38ed0674ae39ec33596c26a47226 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Mon, 10 Jun 2024 11:23:45 +0200 Subject: [PATCH 19/92] feat: add initLegacy function --- .../staking/stakeManager/StakeManager.sol | 12 +++ .../staking/ValidatorShareLegacy.test.js | 18 ++-- .../StakeManager.StakingLegacy.js | 95 +++++++++++++++++-- 3 files changed, 103 insertions(+), 22 deletions(-) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 9efb8ad8..0ddc7da3 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -354,6 +354,18 @@ contract StakeManager is validatorShareFactory = ValidatorShareFactory(_validatorShareFactory); } + function initializeLegacy( + address _tokenNew, + address _migration + ) external onlyGovernance { + migration = IPolygonMigration(_migration); + tokenLegacy = IERC20(token); + token = IERC20(_tokenNew); + uint256 _amount = tokenLegacy.balanceOf(address(this)); + tokenLegacy.approve(_migration, _amount); + migration.migrate(_amount); + } + /** Public Methods */ diff --git a/test/units/staking/ValidatorShareLegacy.test.js b/test/units/staking/ValidatorShareLegacy.test.js index 3c89dde4..8353c352 100644 --- a/test/units/staking/ValidatorShareLegacy.test.js +++ b/test/units/staking/ValidatorShareLegacy.test.js @@ -31,27 +31,21 @@ describe('ValidatorShareLegacy', function () { this.migration = await Migration.deploy(this.legacyToken.address, this.stakeToken.address) - await this.governance.update( - this.stakeManager.address, - this.stakeManager.interface.encodeFunctionData('setStakingToken', [this.stakeToken.address]) - ) + await this.stakeToken.mint(this.migration.address, toWei('30000000')) + await this.legacyToken.mint(this.migration.address, toWei('40000000')) await this.governance.update( this.stakeManager.address, - this.stakeManager.interface.encodeFunctionData('setLegacyToken', [this.legacyToken.address]) + this.stakeManager.interface.encodeFunctionData('setStakingToken', [this.legacyToken.address]) ) + await this.legacyToken.mint(this.stakeManager.address, toWei('10000000')) + await this.governance.update( this.stakeManager.address, - this.stakeManager.interface.encodeFunctionData('setMigration', [this.migration.address]) + this.stakeManager.interface.encodeFunctionData('initializeLegacy', [this.stakeToken.address, this.migration.address]) ) - await this.stakeToken.mint(this.stakeManager.address, toWei('10000000')) - await this.legacyToken.mint(this.stakeManager.address, toWei('10000000')) - - await this.stakeToken.mint(this.migration.address, toWei('30000000')) - await this.legacyToken.mint(this.migration.address, toWei('40000000')) - this.validatorId = '8' this.validatorUser = wallets[0] this.stakeAmount = ValidatorDefaultStake diff --git a/test/units/staking/stakeManager/StakeManager.StakingLegacy.js b/test/units/staking/stakeManager/StakeManager.StakingLegacy.js index 71c05582..dc51814f 100644 --- a/test/units/staking/stakeManager/StakeManager.StakingLegacy.js +++ b/test/units/staking/stakeManager/StakeManager.StakingLegacy.js @@ -43,7 +43,7 @@ export function doUnstake(wallet) { export function prepareForTest(dynastyValue, validatorThreshold) { return async function () { - await freshDeploy.call(this) + await freshDeploy.call(this, true) await this.governance.update( this.stakeManager.address, @@ -58,13 +58,75 @@ export function prepareForTest(dynastyValue, validatorThreshold) { } describe('migrate matic', function (){ + describe('initializeLegacy', function(){ + before('Setup migration scenario', async function() { + await freshDeploy.call(this) + }) + + describe('must revert with legacy functions', function(){ + let stakeTokenUser, user, stakeManagerUser, amount, userPubkey + before('', async function(){ + userPubkey = wallets[1].getPublicKeyString(), + user = wallets[1].getChecksumAddressString() + amount = web3.utils.toWei('10') + + stakeTokenUser = this.stakeToken.connect(this.stakeToken.provider.getSigner(user)) + stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) + }) + + it('on stake token', async function () { + await stakeTokenUser.approve(this.stakeManager.address, amount.toString()) + await expect(stakeManagerUser.stakeForLegacy(user, amount.toString(), web3.utils.toWei('1'), false, userPubkey)) + .to.be.rejectedWith('function call to a non-contract account') + }) + }) + + describe('run initializeLegacy', function(){ + let oldStakeToken, newStakeToken, migrationAmount + before('gov update', async function(){ + migrationAmount = web3.utils.toWei('20000000') + + oldStakeToken = await TestToken.deploy('MATIC', 'MAT') + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('setStakingToken', [oldStakeToken.address]) + ) + await oldStakeToken.mint(this.stakeManager.address, migrationAmount) + + newStakeToken = await TestToken.deploy('POL', 'POL') + + this.migration = await Migration.deploy(oldStakeToken.address, newStakeToken.address) + + await oldStakeToken.mint(this.migration.address, web3.utils.toWei('50000000')) + await newStakeToken.mint(this.migration.address, web3.utils.toWei('50000000')) + }) + + it('must initLegacy', async function () { + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('initializeLegacy', [newStakeToken.address, this.migration.address]) + ) + }) + + it('stakemanager must have correct legacy balance', async function () { + let legacyBalance = await oldStakeToken.balanceOf(this.stakeManager.address) + assertBigNumberEquality(BN(0), legacyBalance) + }) + + it('stakemanager must have correct stake balance', async function () { + let stakeBalance = await newStakeToken.balanceOf(this.stakeManager.address) + assertBigNumberEquality(migrationAmount, stakeBalance) + }) + }) + }) + describe('successful migration', function(){ const migrationAmount = new BN('100000000000000') const initalLegacyAmount = new BN('100000000000000') const initalStakeAmount = new BN(0) before('Setup migration scenario', async function() { - await freshDeploy.call(this) + await freshDeploy.call(this, true) this.stakeToken = await TestToken.deploy('POL', 'POL') this.legacyToken = await TestToken.deploy('MATIC', 'MATIC') @@ -273,7 +335,9 @@ describe('stake Legacy', function () { } describe('double stake', async function () { - before(freshDeploy) + before('deploy', async function() { + await freshDeploy.call(this, true) + }) describe('when stakes first time', function () { const amounts = walletAmounts[wallets[1].getAddressString()] @@ -297,7 +361,9 @@ describe('stake Legacy', function () { }) describe('stake and restake following by another stake', function () { - before(freshDeploy) + before('deploy', async function() { + await freshDeploy.call(this, true) + }) const amounts = walletAmounts[wallets[2].getAddressString()] before('Stake', doStake(wallets[2])) @@ -369,7 +435,9 @@ describe('stake Legacy', function () { }) describe('consecutive stakes', function () { - before(freshDeploy) + before('deploy', async function() { + await freshDeploy.call(this, true) + }) it('validatorId must increment 1 by 1', async function () { const _wallets = [wallets[1], wallets[2], wallets[3]] @@ -387,7 +455,9 @@ describe('stake Legacy', function () { }) describe('stake with heimdall fee', function () { - before(freshDeploy) + before('deploy', async function() { + await freshDeploy.call(this, true) + }) testStake( wallets[0].getChecksumAddressString(), @@ -403,7 +473,9 @@ describe('stake Legacy', function () { const AliceWallet = wallets[1] const newSigner = wallets[2].getPublicKeyString() - before(freshDeploy) + before('deploy', async function() { + await freshDeploy.call(this, true) + }) before(doStake(AliceWallet)) before('Change signer', async function () { const signerUpdateLimit = await this.stakeManager.signerUpdateLimit() @@ -430,7 +502,9 @@ describe('unstake Legacy', function () { const AliceNewWallet = wallets[2] let stakeManagerAlice - before(freshDeploy) + before('deploy', async function() { + await freshDeploy.call(this, true) + }) before(doStake(AliceWallet)) before(doStake(BobWallet)) before('Change signer', async function () { @@ -611,7 +685,9 @@ describe('unstake Legacy', function () { }) describe('reverts', function () { - beforeEach('Fresh Deploy', freshDeploy) + beforeEach('deploy', async function() { + await freshDeploy.call(this, true) + }) const user = wallets[2].getChecksumAddressString() let stakeManagerUser @@ -626,7 +702,6 @@ describe('unstake Legacy', function () { it('when user is not staker', async function () { const validatorId = await this.stakeManager.getValidatorId(user) const stakeManager3 = this.stakeManager.connect(this.stakeManager.provider.getSigner(3)) - await expectRevert.unspecified(stakeManager3.unstakeLegacy(validatorId)) }) From 2517086e7e1f90812095ee71dd664c23ec907b6b Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Wed, 12 Jun 2024 16:07:47 +0200 Subject: [PATCH 20/92] fix: remove unused function --- .../staking/stakeManager/StakeManager.sol | 34 +++---------------- 1 file changed, 5 insertions(+), 29 deletions(-) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 0ddc7da3..28e30019 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -369,12 +369,12 @@ contract StakeManager is /** Public Methods */ - // @note topUpForFee + // @note Doesn't need a legacy version function topUpForFee(address user, uint256 heimdallFee) public onlyWhenUnlocked { _transferAndTopUp(user, msg.sender, heimdallFee, 0, false); } - // @note claimFee + // @note Doesn't need a legacy version function claimFee(uint256 accumFeeAmount, uint256 index, bytes memory proof) public { _claimFee(accumFeeAmount, index, proof, false); } @@ -438,35 +438,10 @@ contract StakeManager is bool acceptDelegation, bytes calldata signerPubkey ) external { - _dethroneAndStake(auctionUser, heimdallFee, validatorId, auctionAmount, acceptDelegation, signerPubkey, false); - } - - // @note - function dethroneAndStakeLegacy( - address auctionUser, - uint256 heimdallFee, - uint256 validatorId, - uint256 auctionAmount, - bool acceptDelegation, - bytes calldata signerPubkey - ) external { - _dethroneAndStake(auctionUser, heimdallFee, validatorId, auctionAmount, acceptDelegation, signerPubkey, true); - } - - // @note - function _dethroneAndStake( - address auctionUser, - uint256 heimdallFee, - uint256 validatorId, - uint256 auctionAmount, - bool acceptDelegation, - bytes memory signerPubkey, - bool legacy - ) internal { require(msg.sender == address(this), "not allowed"); // dethrone - _transferAndTopUp(auctionUser, auctionUser, heimdallFee, 0, legacy); - _unstake(validatorId, currentEpoch, legacy); + _transferAndTopUp(auctionUser, auctionUser, heimdallFee, 0, false); + _unstake(validatorId, currentEpoch, false); uint256 newValidatorId = _stakeFor(auctionUser, auctionAmount, acceptDelegation, signerPubkey); logger.logConfirmAuction(newValidatorId, validatorId, auctionAmount); @@ -1301,6 +1276,7 @@ contract StakeManager is // @note _transferTokenFrom // Do not use this function to transfer from self. function _transferTokenFrom(address from, address destination, uint256 amount, bool legacy) private { + //require(address(this) != from, "No transfer from self"); IERC20 token_ = _getToken(legacy); require(token_.transferFrom(from, destination, amount), "transfer from failed"); if (legacy && destination == address(this)) _convertMaticToPol(amount); From 5287f4edf92694dd399c814e46aebefb6bc2a350 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Thu, 13 Jun 2024 17:28:38 +0200 Subject: [PATCH 21/92] fix: remove legacy parameter at claimFee --- contracts/staking/stakeManager/StakeManager.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 28e30019..a9743e3a 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -376,17 +376,17 @@ contract StakeManager is // @note Doesn't need a legacy version function claimFee(uint256 accumFeeAmount, uint256 index, bytes memory proof) public { - _claimFee(accumFeeAmount, index, proof, false); + _claimFee(accumFeeAmount, index, proof); } // @note - function _claimFee(uint256 accumFeeAmount, uint256 index, bytes memory proof, bool legacy) internal { + function _claimFee(uint256 accumFeeAmount, uint256 index, bytes memory proof) internal { //Ignoring other params because rewards' distribution is on chain require(keccak256(abi.encode(msg.sender, accumFeeAmount)).checkMembership(index, accountStateRoot, proof), "Wrong acc proof"); uint256 withdrawAmount = accumFeeAmount.sub(userFeeExit[msg.sender]); _claimFee(msg.sender, withdrawAmount); userFeeExit[msg.sender] = accumFeeAmount; - _transferToken(msg.sender, withdrawAmount, legacy); + _transferToken(msg.sender, withdrawAmount, false); } function totalStakedFor(address user) external view returns (uint256) { From 8ee1f4539fe573741cdb71612e55a9ad28da360a Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Thu, 13 Jun 2024 22:16:22 +0200 Subject: [PATCH 22/92] fix: remove superfluous init functionality --- .../staking/stakeManager/StakeManager.sol | 20 +----- test/helpers/deployer.js | 61 +++++++++---------- test/units/staking/deployment.js | 15 +---- .../StakeManager.StakingLegacy.js | 13 ++-- 4 files changed, 37 insertions(+), 72 deletions(-) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index a9743e3a..f4ad2d8c 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -79,9 +79,7 @@ contract StakeManager is address _validatorShareFactory, address _governance, address _owner, - address _extensionCode, - address _tokenLegacy, - address _migration + address _extensionCode ) external initializer { require(isContract(_extensionCode), "auction impl incorrect"); extensionCode = _extensionCode; @@ -89,8 +87,6 @@ contract StakeManager is registry = _registry; rootChain = _rootchain; token = IERC20(_token); - tokenLegacy = IERC20(_tokenLegacy); - migration = IPolygonMigration(_migration); NFTContract = StakingNFT(_NFTContract); logger = StakingInfo(_stakingLogger); validatorShareFactory = ValidatorShareFactory(_validatorShareFactory); @@ -222,18 +218,6 @@ contract StakeManager is token = IERC20(_token); } - // @note - function setLegacyToken(address _token) public onlyGovernance { - require(_token != address(0x0)); - tokenLegacy = IERC20(_token); - } - - // @note - function setMigration(address _migration) public onlyGovernance { - require(_migration != address(0x0)); - migration = IPolygonMigration(_migration); - } - /** * @dev Change the number of validators required to allow a passed header root */ @@ -381,7 +365,7 @@ contract StakeManager is // @note function _claimFee(uint256 accumFeeAmount, uint256 index, bytes memory proof) internal { - //Ignoring other params because rewards' distribution is on chain + //Ignoring other params because rewards distribution is on chain require(keccak256(abi.encode(msg.sender, accumFeeAmount)).checkMembership(index, accountStateRoot, proof), "Wrong acc proof"); uint256 withdrawAmount = accumFeeAmount.sub(userFeeExit[msg.sender]); _claimFee(msg.sender, withdrawAmount); diff --git a/test/helpers/deployer.js b/test/helpers/deployer.js index edf7adbb..60e1fb02 100644 --- a/test/helpers/deployer.js +++ b/test/helpers/deployer.js @@ -17,22 +17,13 @@ class Deployer { return contractFactories.EventsHub.attach(proxy.address) } - async freshDeploy(owner, legacy = false) { + async freshDeploy(owner) { this.governance = await this.deployGovernance() this.registry = await contractFactories.Registry.deploy(this.governance.address) this.eventsHub = await this.deployEventsHub(this.registry.address) this.validatorShareFactory = await contractFactories.ValidatorShareFactory.deploy() this.stakeToken = await contractFactories.TestToken.deploy('Stake Token', 'ST') - if (legacy){ - this.legacyToken = await contractFactories.TestToken.deploy('Legacy Token', 'LT') - this.migration = await contractFactories.Migration.deploy(this.legacyToken.address, this.stakeToken.address) - } else { - this.legacyToken = {} - this.migration = {} - this.legacyToken.address = '0x0000000000000000000000000000000000000000' - this.migration.address = '0x0000000000000000000000000000000000000000' - } this.stakingInfo = await contractFactories.StakingInfo.deploy(this.registry.address) this.slashingManager = await contractFactories.SlashingManager.deploy( @@ -57,9 +48,7 @@ class Deployer { this.validatorShareFactory.address, this.governance.address, owner, - auctionImpl.address, - this.legacyToken.address, - this.migration.address + auctionImpl.address ]) ) @@ -104,19 +93,14 @@ class Deployer { this.validatorShare = await contractFactories.ValidatorShare.deploy() this.rootChain = await this.deployRootChain() this.stakingInfo = await contractFactories.StakingInfo.deploy(this.registry.address) - this.stakeToken = await contractFactories.TestToken.deploy('Stake Token', 'STAKE') - - if (legacy) { - this.legacyToken = await contractFactories.TestToken.deploy('Legacy Token', 'LT') - this.migration = await contractFactories.Migration.deploy(this.legacyToken.address, this.stakeToken.address) - // Mint token into migration, so we can actually migrate - await this.stakeToken.mint(this.migration.address, web3.utils.toWei('1000000')) - await this.legacyToken.mint(this.migration.address, web3.utils.toWei('1000000')) + + let token + if (legacy){ + this.legacyToken = await contractFactories.TestToken.deploy('Legacy Token', 'LEG') + token = this.legacyToken } else { - this.legacyToken = {} - this.migration = {} - this.legacyToken.address = '0x0000000000000000000000000000000000000000' - this.migration.address = '0x0000000000000000000000000000000000000000' + this.stakeToken = await contractFactories.TestToken.deploy('Stake Token', 'STAKE') + token = this.stakeToken } this.stakingNFT = await contractFactories.StakingNFT.deploy('Matic Validator', 'MV') @@ -130,15 +114,13 @@ class Deployer { stakeManager.interface.encodeFunctionData('initialize', [ this.registry.address, rootChainOwner.getAddressString(), - this.stakeToken.address, + token.address, this.stakingNFT.address, this.stakingInfo.address, this.validatorShareFactory.address, this.governance.address, wallets[0].getAddressString(), - auctionImpl.address, - this.legacyToken.address, - this.migration.address + auctionImpl.address ]) ) @@ -149,6 +131,22 @@ class Deployer { 'heimdall-P5rXwg' ) + await token.mint(this.stakeManager.address, web3.utils.toWei('10000000')) + + if (legacy){ + this.stakeToken = await contractFactories.TestToken.deploy('POL', 'POL') + + this.migration = await contractFactories.Migration.deploy(this.legacyToken.address, this.stakeToken.address) + + await this.stakeToken.mint(this.migration.address, web3.utils.toWei('50000000')) + await this.legacyToken.mint(this.migration.address, web3.utils.toWei('50000000')) + + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('initializeLegacy', [this.stakeToken.address, this.migration.address]) + ) + } + await this.stakingNFT.transferOwnership(this.stakeManager.address) await this.updateContractMap(ethUtils.keccak256('stakeManager'), this.stakeManager.address) await this.updateContractMap(ethUtils.keccak256('validatorShare'), this.validatorShare.address) @@ -159,14 +157,13 @@ class Deployer { rootChain: this.rootChain, stakeManager: this.stakeManager, stakeToken: this.stakeToken, + legacyToken: this.legacyToken, slashingManager: this.slashingManager, stakingInfo: this.stakingInfo, governance: this.governance, stakingNFT: this.stakingNFT, stakeManagerProxy: proxy, - stakeManagerImpl: stakeManager, - legacyToken: this.legacyToken, - migration: this.migration + stakeManagerImpl: stakeManager } return _contracts } diff --git a/test/units/staking/deployment.js b/test/units/staking/deployment.js index 2a56096e..914c31fd 100644 --- a/test/units/staking/deployment.js +++ b/test/units/staking/deployment.js @@ -37,6 +37,7 @@ export const walletAmounts = { export async function freshDeploy(legacy = false) { let contracts = await deployer.deployStakeManager(wallets, legacy) this.stakeToken = contracts.stakeToken + this.legacyToken = contracts.legacyToken this.stakeManager = contracts.stakeManager this.nftContract = contracts.stakingNFT this.rootChainOwner = contracts.rootChainOwner @@ -44,13 +45,6 @@ export async function freshDeploy(legacy = false) { this.governance = contracts.governance this.validatorShare = deployer.validatorShare this.slashingManager = contracts.slashingManager - if (legacy) { - this.legacyToken = contracts.legacyToken - this.migration = contracts.migration - } else { - this.legacyToken = {} - this.migration = {} - } await this.governance.update( this.stakeManager.address, @@ -62,15 +56,10 @@ export async function freshDeploy(legacy = false) { ) for (const walletAddr in walletAmounts) { + await this.stakeToken.mint(walletAddr, walletAmounts[walletAddr].initialBalance) if (legacy) { await this.legacyToken.mint(walletAddr, walletAmounts[walletAddr].initialBalance) } - await this.stakeToken.mint(walletAddr, walletAmounts[walletAddr].initialBalance) - } - - await this.stakeToken.mint(this.stakeManager.address, web3.utils.toWei('10000000')) - if (legacy) { - await this.legacyToken.mint(this.stakeManager.address, web3.utils.toWei('20000000')) } this.defaultHeimdallFee = new BN(web3.utils.toWei('1')) diff --git a/test/units/staking/stakeManager/StakeManager.StakingLegacy.js b/test/units/staking/stakeManager/StakeManager.StakingLegacy.js index dc51814f..6951aee6 100644 --- a/test/units/staking/stakeManager/StakeManager.StakingLegacy.js +++ b/test/units/staking/stakeManager/StakeManager.StakingLegacy.js @@ -126,7 +126,7 @@ describe('migrate matic', function (){ const initalStakeAmount = new BN(0) before('Setup migration scenario', async function() { - await freshDeploy.call(this, true) + await freshDeploy.call(this) this.stakeToken = await TestToken.deploy('POL', 'POL') this.legacyToken = await TestToken.deploy('MATIC', 'MATIC') @@ -135,17 +135,12 @@ describe('migrate matic', function (){ await this.governance.update( this.stakeManager.address, - this.stakeManager.interface.encodeFunctionData('setStakingToken', [this.stakeToken.address]) - ) - - await this.governance.update( - this.stakeManager.address, - this.stakeManager.interface.encodeFunctionData('setLegacyToken', [this.legacyToken.address]) + this.stakeManager.interface.encodeFunctionData('setStakingToken', [this.legacyToken.address]) ) - + await this.governance.update( this.stakeManager.address, - this.stakeManager.interface.encodeFunctionData('setMigration', [this.migration.address]) + this.stakeManager.interface.encodeFunctionData('initializeLegacy', [this.stakeToken.address, this.migration.address]) ) await this.stakeToken.mint(this.stakeManager.address, initalStakeAmount.toString()) From a85d63d703227b360e3f12bc18f6e937a791e76c Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Mon, 17 Jun 2024 18:41:16 +0200 Subject: [PATCH 23/92] fix: typos --- contracts/staking/stakeManager/StakeManager.sol | 2 +- contracts/staking/validatorShare/ValidatorShare.sol | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index f4ad2d8c..7ef8fa4a 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -1026,7 +1026,7 @@ contract StakeManager is uint256 initialRewardPerStake = validators[validatorId].initialRewardPerStake; - // attempt to save gas in case if rewards were updated previosuly + // attempt to save gas in case if rewards were updated previously if (initialRewardPerStake < currentRewardPerStake) { uint256 validatorsStake = validators[validatorId].amount; uint256 delegatedAmount = validators[validatorId].delegatedAmount; diff --git a/contracts/staking/validatorShare/ValidatorShare.sol b/contracts/staking/validatorShare/ValidatorShare.sol index 95ae7536..2294eb08 100644 --- a/contracts/staking/validatorShare/ValidatorShare.sol +++ b/contracts/staking/validatorShare/ValidatorShare.sol @@ -17,7 +17,7 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I } uint256 constant EXCHANGE_RATE_PRECISION = 100; - // maximum matic possible, even if rate will be 1 and all matic will be staken in one go, it will result in 10 ^ 58 shares + // maximum matic possible, even if rate will be 1 and all matic will be staked in one go, it will result in 10 ^ 58 shares uint256 constant EXCHANGE_RATE_HIGH_PRECISION = 10**29; uint256 constant MAX_COMMISION_RATE = 100; uint256 constant REWARD_PRECISION = 10**25; @@ -188,7 +188,7 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I DelegatorUnbond memory unbond = unbonds[msg.sender]; unbond.shares = unbond.shares.add(_withdrawPoolShare); - // refresh undond period + // refresh unbond period unbond.withdrawEpoch = stakeManager.epoch(); unbonds[msg.sender] = unbond; From 3652d8b95325e516bae36485d088da0282c61406 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Wed, 19 Jun 2024 13:54:12 +0200 Subject: [PATCH 24/92] feat: disable slashing --- .../staking/stakeManager/StakeManager.sol | 66 ++++--------------- 1 file changed, 12 insertions(+), 54 deletions(-) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 7ef8fa4a..186c4006 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -764,49 +764,7 @@ contract StakeManager is // @note slash function slash(bytes calldata _slashingInfoList) external returns (uint256) { - require(Registry(registry).getSlashingManagerAddress() == msg.sender, "Not slash manager"); - - RLPReader.RLPItem[] memory slashingInfoList = _slashingInfoList.toRlpItem().toList(); - int256 valJailed; - uint256 jailedAmount; - uint256 totalAmount; - uint256 i; - - for (; i < slashingInfoList.length; i++) { - RLPReader.RLPItem[] memory slashData = slashingInfoList[i].toList(); - - uint256 validatorId = slashData[0].toUint(); - _updateRewards(validatorId); - - uint256 _amount = slashData[1].toUint(); - totalAmount = totalAmount.add(_amount); - - address delegationContract = validators[validatorId].contractAddress; - if (delegationContract != address(0x0)) { - uint256 delSlashedAmount = - IValidatorShare(delegationContract).slash( - validators[validatorId].amount, - validators[validatorId].delegatedAmount, - _amount - ); - _amount = _amount.sub(delSlashedAmount); - } - - uint256 validatorStakeSlashed = validators[validatorId].amount.sub(_amount); - validators[validatorId].amount = validatorStakeSlashed; - - if (validatorStakeSlashed == 0) { - _unstake(validatorId, currentEpoch, false); - } else if (slashData[2].toBoolean()) { - jailedAmount = jailedAmount.add(_jail(validatorId, 1)); - valJailed++; - } - } - - //update timeline - updateTimeline(-int256(totalAmount.add(jailedAmount)), -valJailed, 0); - - return totalAmount; + revert(); } function unjail(uint256 validatorId) public onlyStaker(validatorId) { @@ -1141,18 +1099,18 @@ contract StakeManager is ); } - function _jail(uint256 validatorId, uint256 jailCheckpoints) internal returns (uint256) { - address delegationContract = validators[validatorId].contractAddress; - if (delegationContract != address(0x0)) { - IValidatorShare(delegationContract).lock(); - } + // function _jail(uint256 validatorId, uint256 jailCheckpoints) internal returns (uint256) { + // address delegationContract = validators[validatorId].contractAddress; + // if (delegationContract != address(0x0)) { + // IValidatorShare(delegationContract).lock(); + // } - uint256 _currentEpoch = currentEpoch; - validators[validatorId].jailTime = _currentEpoch.add(jailCheckpoints); - validators[validatorId].status = Status.Locked; - logger.logJailed(validatorId, _currentEpoch, validators[validatorId].signer); - return validators[validatorId].amount.add(validators[validatorId].delegatedAmount); - } + // uint256 _currentEpoch = currentEpoch; + // validators[validatorId].jailTime = _currentEpoch.add(jailCheckpoints); + // validators[validatorId].status = Status.Locked; + // logger.logJailed(validatorId, _currentEpoch, validators[validatorId].signer); + // return validators[validatorId].amount.add(validators[validatorId].delegatedAmount); + // } function _stakeFor( address user, From 3b60b2361f6f9f5885ea76a5359370801326b789 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Wed, 19 Jun 2024 13:56:32 +0200 Subject: [PATCH 25/92] feat: reduce codesize --- .../staking/stakeManager/StakeManager.sol | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 186c4006..3f7d634f 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -345,9 +345,7 @@ contract StakeManager is migration = IPolygonMigration(_migration); tokenLegacy = IERC20(token); token = IERC20(_tokenNew); - uint256 _amount = tokenLegacy.balanceOf(address(this)); - tokenLegacy.approve(_migration, _amount); - migration.migrate(_amount); + _convertMaticToPol(tokenLegacy.balanceOf(address(this))); } /** @@ -368,7 +366,9 @@ contract StakeManager is //Ignoring other params because rewards distribution is on chain require(keccak256(abi.encode(msg.sender, accumFeeAmount)).checkMembership(index, accountStateRoot, proof), "Wrong acc proof"); uint256 withdrawAmount = accumFeeAmount.sub(userFeeExit[msg.sender]); - _claimFee(msg.sender, withdrawAmount); + totalHeimdallFee = totalHeimdallFee.sub(withdrawAmount); + logger.logClaimFee(msg.sender, withdrawAmount); + // _claimFee(msg.sender, withdrawAmount); userFeeExit[msg.sender] = accumFeeAmount; _transferToken(msg.sender, withdrawAmount, false); } @@ -1232,10 +1232,10 @@ contract StakeManager is logger.logTopUpFee(user, fee); } - function _claimFee(address user, uint256 amount) private { - totalHeimdallFee = totalHeimdallFee.sub(amount); - logger.logClaimFee(user, amount); - } + // function _claimFee(address user, uint256 amount) private { + // totalHeimdallFee = totalHeimdallFee.sub(amount); + // logger.logClaimFee(user, amount); + // } function _insertSigner(address newSigner) internal { signers.push(newSigner); @@ -1282,13 +1282,13 @@ contract StakeManager is } function _convertMaticToPol(uint256 amount) internal { - require(tokenLegacy.balanceOf(address(this)) >= amount, "Insufficient MATIC balance"); + require(tokenLegacy.balanceOf(address(this)) >= amount, "Lacking MATIC"); tokenLegacy.approve(address(migration), amount); migration.migrate(amount); } function _convertPolToMatic(uint256 amount) internal { - require(token.balanceOf(address(this)) >= amount, "Insufficient POL balance"); + require(token.balanceOf(address(this)) >= amount, "Lacking POL"); token.approve(address(migration), amount); migration.unmigrate(amount); } From 2bce548ddf2e67fe0ace6f71a94bf74d00fa9a09 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Wed, 19 Jun 2024 13:57:28 +0200 Subject: [PATCH 26/92] fix: tests --- test/helpers/deployer.js | 4 ++-- test/units/staking/deployment.js | 4 ++++ test/units/staking/stakeManager/StakeManager.test.js | 2 -- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/test/helpers/deployer.js b/test/helpers/deployer.js index 60e1fb02..292faa46 100644 --- a/test/helpers/deployer.js +++ b/test/helpers/deployer.js @@ -131,9 +131,9 @@ class Deployer { 'heimdall-P5rXwg' ) - await token.mint(this.stakeManager.address, web3.utils.toWei('10000000')) - if (legacy){ + await token.mint(this.stakeManager.address, web3.utils.toWei('10000000')) + this.stakeToken = await contractFactories.TestToken.deploy('POL', 'POL') this.migration = await contractFactories.Migration.deploy(this.legacyToken.address, this.stakeToken.address) diff --git a/test/units/staking/deployment.js b/test/units/staking/deployment.js index 914c31fd..8eba92e7 100644 --- a/test/units/staking/deployment.js +++ b/test/units/staking/deployment.js @@ -62,6 +62,10 @@ export async function freshDeploy(legacy = false) { } } + if (!legacy) { + await this.stakeToken.mint(this.stakeManager.address, web3.utils.toWei('10000000')) + } + this.defaultHeimdallFee = new BN(web3.utils.toWei('1')) } diff --git a/test/units/staking/stakeManager/StakeManager.test.js b/test/units/staking/stakeManager/StakeManager.test.js index 10b278f2..debb75db 100644 --- a/test/units/staking/stakeManager/StakeManager.test.js +++ b/test/units/staking/stakeManager/StakeManager.test.js @@ -92,8 +92,6 @@ describe('StakeManager', function (accounts) { ZeroAddr, ZeroAddr, ZeroAddr, - ZeroAddr, - ZeroAddr, ZeroAddr ), 'already inited' From 94fd55f967d3d13a8856f7a010987380e756c0bc Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Thu, 20 Jun 2024 11:55:56 +0200 Subject: [PATCH 27/92] fix: rename Migration contract --- .../common/misc/{Migration.sol => PolygonMigration.sol} | 0 test/helpers/artifacts.js | 2 +- test/helpers/deployer.js | 2 +- test/units/staking/ValidatorShareLegacy.test.js | 4 ++-- .../staking/stakeManager/StakeManager.StakingLegacy.js | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) rename contracts/common/misc/{Migration.sol => PolygonMigration.sol} (100%) diff --git a/contracts/common/misc/Migration.sol b/contracts/common/misc/PolygonMigration.sol similarity index 100% rename from contracts/common/misc/Migration.sol rename to contracts/common/misc/PolygonMigration.sol diff --git a/test/helpers/artifacts.js b/test/helpers/artifacts.js index a6f6222f..f882fa35 100644 --- a/test/helpers/artifacts.js +++ b/test/helpers/artifacts.js @@ -49,7 +49,7 @@ export const ExitNFT = await ethers.getContractFactory('ExitNFT') export const GnosisSafeProxy = await ethers.getContractFactory('GnosisSafeProxy') export const GnosisSafe = await ethers.getContractFactory('GnosisSafe') export const PolygonMigrationTest = await ethers.getContractFactory('PolygonMigrationTest') -export const Migration = await ethers.getContractFactory('PolygonMigration') +export const PolygonMigration = await ethers.getContractFactory('PolygonMigration') // child chain const borProvider = new ethers.providers.JsonRpcProvider( diff --git a/test/helpers/deployer.js b/test/helpers/deployer.js index 292faa46..c6e2f0e3 100644 --- a/test/helpers/deployer.js +++ b/test/helpers/deployer.js @@ -136,7 +136,7 @@ class Deployer { this.stakeToken = await contractFactories.TestToken.deploy('POL', 'POL') - this.migration = await contractFactories.Migration.deploy(this.legacyToken.address, this.stakeToken.address) + this.migration = await contractFactories.PolygonMigration.deploy(this.legacyToken.address, this.stakeToken.address) await this.stakeToken.mint(this.migration.address, web3.utils.toWei('50000000')) await this.legacyToken.mint(this.migration.address, web3.utils.toWei('50000000')) diff --git a/test/units/staking/ValidatorShareLegacy.test.js b/test/units/staking/ValidatorShareLegacy.test.js index 8353c352..e2c5bfae 100644 --- a/test/units/staking/ValidatorShareLegacy.test.js +++ b/test/units/staking/ValidatorShareLegacy.test.js @@ -1,4 +1,4 @@ -import {Migration, TestToken, ValidatorShare, StakingInfo, EventsHub } from '../../helpers/artifacts.js' +import {PolygonMigration, TestToken, ValidatorShare, StakingInfo, EventsHub } from '../../helpers/artifacts.js' import testHelpers from '@openzeppelin/test-helpers' import { checkPoint, assertBigNumberEquality, updateSlashedAmounts, assertInTransaction } from '../../helpers/utils.js' import { wallets, freshDeploy, approveAndStake } from './deployment.js' @@ -29,7 +29,7 @@ describe('ValidatorShareLegacy', function () { this.stakeToken = await TestToken.deploy('POL', 'POL') this.legacyToken = await TestToken.deploy('MATIC', 'MATIC') - this.migration = await Migration.deploy(this.legacyToken.address, this.stakeToken.address) + this.migration = await PolygonMigration.deploy(this.legacyToken.address, this.stakeToken.address) await this.stakeToken.mint(this.migration.address, toWei('30000000')) await this.legacyToken.mint(this.migration.address, toWei('40000000')) diff --git a/test/units/staking/stakeManager/StakeManager.StakingLegacy.js b/test/units/staking/stakeManager/StakeManager.StakingLegacy.js index 6951aee6..f3fec738 100644 --- a/test/units/staking/stakeManager/StakeManager.StakingLegacy.js +++ b/test/units/staking/stakeManager/StakeManager.StakingLegacy.js @@ -1,4 +1,4 @@ -import { StakingInfo, TestToken, Migration, ValidatorShare } from '../../../helpers/artifacts.js' +import { StakingInfo, TestToken, PolygonMigration, ValidatorShare } from '../../../helpers/artifacts.js' import { checkPoint, assertBigNumberEquality, assertBigNumbergt } from '../../../helpers/utils.js' import testHelpers from '@openzeppelin/test-helpers' @@ -95,7 +95,7 @@ describe('migrate matic', function (){ newStakeToken = await TestToken.deploy('POL', 'POL') - this.migration = await Migration.deploy(oldStakeToken.address, newStakeToken.address) + this.migration = await PolygonMigration.deploy(oldStakeToken.address, newStakeToken.address) await oldStakeToken.mint(this.migration.address, web3.utils.toWei('50000000')) await newStakeToken.mint(this.migration.address, web3.utils.toWei('50000000')) @@ -131,7 +131,7 @@ describe('migrate matic', function (){ this.stakeToken = await TestToken.deploy('POL', 'POL') this.legacyToken = await TestToken.deploy('MATIC', 'MATIC') - this.migration = await Migration.deploy(this.legacyToken.address, this.stakeToken.address) + this.migration = await PolygonMigration.deploy(this.legacyToken.address, this.stakeToken.address) await this.governance.update( this.stakeManager.address, From b7568fd84215d49e31d712f10c7813e406a47f94 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Thu, 20 Jun 2024 11:56:31 +0200 Subject: [PATCH 28/92] fix: inline _claimFee --- contracts/staking/stakeManager/StakeManager.sol | 7 ------- 1 file changed, 7 deletions(-) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 3f7d634f..653df720 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -358,17 +358,10 @@ contract StakeManager is // @note Doesn't need a legacy version function claimFee(uint256 accumFeeAmount, uint256 index, bytes memory proof) public { - _claimFee(accumFeeAmount, index, proof); - } - - // @note - function _claimFee(uint256 accumFeeAmount, uint256 index, bytes memory proof) internal { - //Ignoring other params because rewards distribution is on chain require(keccak256(abi.encode(msg.sender, accumFeeAmount)).checkMembership(index, accountStateRoot, proof), "Wrong acc proof"); uint256 withdrawAmount = accumFeeAmount.sub(userFeeExit[msg.sender]); totalHeimdallFee = totalHeimdallFee.sub(withdrawAmount); logger.logClaimFee(msg.sender, withdrawAmount); - // _claimFee(msg.sender, withdrawAmount); userFeeExit[msg.sender] = accumFeeAmount; _transferToken(msg.sender, withdrawAmount, false); } From ab70c89a8956e2872fb2422d99db0a4899568939 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Thu, 20 Jun 2024 12:16:25 +0200 Subject: [PATCH 29/92] fix: remove unused code --- .../staking/stakeManager/StakeManager.sol | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 653df720..2ca49a03 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -1092,19 +1092,6 @@ contract StakeManager is ); } - // function _jail(uint256 validatorId, uint256 jailCheckpoints) internal returns (uint256) { - // address delegationContract = validators[validatorId].contractAddress; - // if (delegationContract != address(0x0)) { - // IValidatorShare(delegationContract).lock(); - // } - - // uint256 _currentEpoch = currentEpoch; - // validators[validatorId].jailTime = _currentEpoch.add(jailCheckpoints); - // validators[validatorId].status = Status.Locked; - // logger.logJailed(validatorId, _currentEpoch, validators[validatorId].signer); - // return validators[validatorId].amount.add(validators[validatorId].delegatedAmount); - // } - function _stakeFor( address user, uint256 amount, @@ -1211,7 +1198,6 @@ contract StakeManager is // @note _transferTokenFrom // Do not use this function to transfer from self. function _transferTokenFrom(address from, address destination, uint256 amount, bool legacy) private { - //require(address(this) != from, "No transfer from self"); IERC20 token_ = _getToken(legacy); require(token_.transferFrom(from, destination, amount), "transfer from failed"); if (legacy && destination == address(this)) _convertMaticToPol(amount); @@ -1225,11 +1211,6 @@ contract StakeManager is logger.logTopUpFee(user, fee); } - // function _claimFee(address user, uint256 amount) private { - // totalHeimdallFee = totalHeimdallFee.sub(amount); - // logger.logClaimFee(user, amount); - // } - function _insertSigner(address newSigner) internal { signers.push(newSigner); From a9990cbcfbce0f7a73a564b1250a29ab5b877a6c Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Thu, 20 Jun 2024 12:39:12 +0200 Subject: [PATCH 30/92] fix: inline migrate functions again --- contracts/staking/validatorShare/ValidatorShare.sol | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/contracts/staking/validatorShare/ValidatorShare.sol b/contracts/staking/validatorShare/ValidatorShare.sol index 2294eb08..231a0c6d 100644 --- a/contracts/staking/validatorShare/ValidatorShare.sol +++ b/contracts/staking/validatorShare/ValidatorShare.sol @@ -215,11 +215,6 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I // @note migrateOut function migrateOut(address user, uint256 amount) external onlyOwner { - _migrateOut(user, amount); - } - - // @note - function _migrateOut(address user, uint256 amount) internal { _withdrawAndTransferReward(user, false); (uint256 totalStaked, uint256 rate) = getTotalStake(user); require(totalStaked >= amount, "Migrating too much"); @@ -238,14 +233,9 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I // @note migrateIn function migrateIn(address user, uint256 amount) external onlyOwner { - _migrateIn(user, amount); - } - - // @note - function _migrateIn(address user, uint256 amount) internal { _withdrawAndTransferReward(user, false); _buyShares(amount, 0, user); - } + } // @note unstakeClaimTokens function unstakeClaimTokens() public { From 36a610645f296e15a220788db5716d181aa393d6 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Thu, 20 Jun 2024 12:57:31 +0200 Subject: [PATCH 31/92] fix: remove all notes --- .../staking/stakeManager/StakeManager.sol | 38 ------------------- .../staking/validatorShare/ValidatorShare.sol | 27 ------------- 2 files changed, 65 deletions(-) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 2ca49a03..39b847b7 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -198,13 +198,11 @@ contract StakeManager is delegationEnabled = enabled; } - // @note forceUnstake // Housekeeping function. @todo remove later function forceUnstake(uint256 validatorId) external onlyGovernance { _unstake(validatorId, currentEpoch, false); } - // @note function forceUnstakeLegacy(uint256 validatorId) external onlyGovernance { _unstake(validatorId, currentEpoch, true); } @@ -319,7 +317,6 @@ contract StakeManager is IValidatorShare(contractAddr).drain(tokenAddr, destination, amount); } - // @note drain function drain(address destination, uint256 amount) external onlyGovernance { _transferToken(destination, amount, false); } @@ -351,12 +348,10 @@ contract StakeManager is /** Public Methods */ - // @note Doesn't need a legacy version function topUpForFee(address user, uint256 heimdallFee) public onlyWhenUnlocked { _transferAndTopUp(user, msg.sender, heimdallFee, 0, false); } - // @note Doesn't need a legacy version function claimFee(uint256 accumFeeAmount, uint256 index, bytes memory proof) public { require(keccak256(abi.encode(msg.sender, accumFeeAmount)).checkMembership(index, accountStateRoot, proof), "Wrong acc proof"); uint256 withdrawAmount = accumFeeAmount.sub(userFeeExit[msg.sender]); @@ -406,7 +401,6 @@ contract StakeManager is ); } - // @note dethroneAndStake function dethroneAndStake( address auctionUser, uint256 heimdallFee, @@ -424,17 +418,14 @@ contract StakeManager is logger.logConfirmAuction(newValidatorId, validatorId, auctionAmount); } - // @note unstake function unstake(uint256 validatorId) external onlyStaker(validatorId) { _unstake(validatorId, false); } - // @note function unstakeLegacy(uint256 validatorId) external onlyStaker(validatorId) { _unstake(validatorId, true); } - // @note function _unstake(uint256 validatorId, bool legacy) internal { require(validatorAuction[validatorId].amount == 0); @@ -449,17 +440,14 @@ contract StakeManager is _unstake(validatorId, exitEpoch, legacy); } - // @note transferFunds function transferFunds(uint256 validatorId, uint256 amount, address delegator) external returns (bool) { return _transferFunds(validatorId, amount, delegator, false); } - // @note function transferFundsLegacy(uint256 validatorId, uint256 amount, address delegator) external returns (bool) { return _transferFunds(validatorId, amount, delegator, true); } - // @note function _transferFunds(uint256 validatorId, uint256 amount, address delegator, bool legacy) internal returns (bool) { require(validators[validatorId].contractAddress == msg.sender || Registry(registry).getSlashingManagerAddress() == msg.sender, "not allowed"); if (legacy) _convertPolToMatic(amount); @@ -467,17 +455,14 @@ contract StakeManager is return token_.transfer(delegator, amount); } - // @note delegationDeposit function delegationDeposit(uint256 validatorId, uint256 amount, address delegator) external onlyDelegation(validatorId) returns (bool) { return _delegationDeposit(amount, delegator, false); } - // @note function delegationDepositLegacy(uint256 validatorId, uint256 amount, address delegator) external onlyDelegation(validatorId) returns (bool) { return _delegationDeposit(amount, delegator, true); } - // @note function _delegationDeposit(uint256 amount, address delegator, bool legacy) internal returns (bool) { IERC20 token_ = _getToken(legacy); token_.transferFrom(delegator, address(this), amount); @@ -485,17 +470,14 @@ contract StakeManager is return true; } - // @note stakeFor function stakeFor(address user, uint256 amount, uint256 heimdallFee, bool acceptDelegation, bytes memory signerPubkey) public onlyWhenUnlocked { _stakeFor(user, amount, heimdallFee, acceptDelegation, signerPubkey, false); } - // @note function stakeForLegacy(address user, uint256 amount, uint256 heimdallFee, bool acceptDelegation, bytes memory signerPubkey) public onlyWhenUnlocked { _stakeFor(user, amount, heimdallFee, acceptDelegation, signerPubkey, true); } - // @note function _stakeFor(address user, uint256 amount, uint256 heimdallFee, bool acceptDelegation, bytes memory signerPubkey, bool legacy) internal { require(currentValidatorSetSize() < validatorThreshold, "no more slots"); require(amount >= minDeposit, "not enough deposit"); @@ -503,17 +485,14 @@ contract StakeManager is _stakeFor(user, amount, acceptDelegation, signerPubkey); } - // @note unstakeClaim function unstakeClaim(uint256 validatorId) public onlyStaker(validatorId) { _unstakeClaim(validatorId, false); } - // @note function unstakeClaimLegacy(uint256 validatorId) public onlyStaker(validatorId) { _unstakeClaim(validatorId, true); } - // @note function _unstakeClaim(uint256 validatorId, bool legacy) internal { uint256 deactivationEpoch = validators[validatorId].deactivationEpoch; // can only claim stake back after WITHDRAWAL_DELAY @@ -543,17 +522,14 @@ contract StakeManager is logger.logUnstaked(msg.sender, validatorId, amount, newTotalStaked); } - // @note restake function restake(uint256 validatorId, uint256 amount, bool stakeRewards) public onlyWhenUnlocked onlyStaker(validatorId) { _restake(validatorId, amount, stakeRewards, false); } - // @note function restakeLegacy(uint256 validatorId, uint256 amount, bool stakeRewards) public onlyWhenUnlocked onlyStaker(validatorId) { _restake(validatorId, amount, stakeRewards, true); } - // @note function _restake(uint256 validatorId, uint256 amount, bool stakeRewards, bool legacy) internal { require(validators[validatorId].deactivationEpoch == 0, "No restaking"); @@ -578,17 +554,14 @@ contract StakeManager is logger.logRestaked(validatorId, validators[validatorId].amount, newTotalStaked); } - // @note withdrawRewards function withdrawRewards(uint256 validatorId) public onlyStaker(validatorId) { _withdrawRewards(validatorId, false); } - // @note function withdrawRewardsLegacy(uint256 validatorId) public onlyStaker(validatorId) { _withdrawRewards(validatorId, true); } - // @note function _withdrawRewards(uint256 validatorId, bool legacy) internal { _updateRewards(validatorId); _liquidateRewards(validatorId, msg.sender, legacy); @@ -755,7 +728,6 @@ contract StakeManager is return totalReward; } - // @note slash function slash(bytes calldata _slashingInfoList) external returns (uint256) { revert(); } @@ -1139,7 +1111,6 @@ contract StakeManager is return validatorId; } - // @note _unstake function _unstake(uint256 validatorId, uint256 exitEpoch, bool legacy) internal { // TODO: if validators unstake and slashed to 0, he will be forced to unstake again // must think how to handle it correctly @@ -1179,7 +1150,6 @@ contract StakeManager is currentEpoch = nextEpoch; } - // @note _liquidateRewards function _liquidateRewards(uint256 validatorId, address validatorUser, bool legacy) private { uint256 reward = validators[validatorId].reward.sub(INITIALIZED_AMOUNT); totalRewardsLiquidated = totalRewardsLiquidated.add(reward); @@ -1188,14 +1158,12 @@ contract StakeManager is logger.logClaimRewards(validatorId, reward, totalRewardsLiquidated); } - // @note _transferToken function _transferToken(address destination, uint256 amount, bool legacy) private { if (legacy) _convertPolToMatic(amount); IERC20 token_ = _getToken(legacy); require(token_.transfer(destination, amount), "transfer failed"); } - // @note _transferTokenFrom // Do not use this function to transfer from self. function _transferTokenFrom(address from, address destination, uint256 amount, bool legacy) private { IERC20 token_ = _getToken(legacy); @@ -1203,7 +1171,6 @@ contract StakeManager is if (legacy && destination == address(this)) _convertMaticToPol(amount); } - // @note function _transferAndTopUp(address user, address from, uint256 fee, uint256 additionalAmount, bool legacy) private { require(fee >= minHeimdallFee, "fee too small"); _transferTokenFrom(from, address(this), fee.add(additionalAmount), legacy); @@ -1246,11 +1213,6 @@ contract StakeManager is signers.length = totalSigners - 1; } - // ------------------------------------------------------------------------ - // @note MATIC <=> POL CONVERSION - // ------------------------------------------------------------------------ - - // NOTE Convert all. function convertMaticToPol(uint256 amount) external onlyGovernance { _convertMaticToPol(amount); } diff --git a/contracts/staking/validatorShare/ValidatorShare.sol b/contracts/staking/validatorShare/ValidatorShare.sol index 231a0c6d..fd77806c 100644 --- a/contracts/staking/validatorShare/ValidatorShare.sol +++ b/contracts/staking/validatorShare/ValidatorShare.sol @@ -108,17 +108,14 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I /** Public Methods */ - // @note buyVoucher function buyVoucher(uint256 _amount, uint256 _minSharesToMint) public returns (uint256 amountToDeposit) { return _buyVoucher(_amount, _minSharesToMint, false); } - // @note function buyVoucherLegacy(uint256 _amount, uint256 _minSharesToMint) public returns (uint256 amountToDeposit) { return _buyVoucher(_amount, _minSharesToMint, true); } - // @note function _buyVoucher(uint256 _amount, uint256 _minSharesToMint, bool legacy) internal returns (uint256 amountToDeposit) { _withdrawAndTransferReward(msg.sender, legacy); @@ -133,17 +130,14 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I return amountToDeposit; } - // @note restake function restake() public returns (uint256, uint256) { return _restake(false); } - // @note function restakeLegacy() public returns (uint256, uint256) { return _restake(true); } - // @note function _restake(bool legacy) public returns (uint256, uint256) { address user = msg.sender; uint256 liquidReward = _withdrawReward(user); @@ -172,17 +166,14 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I return (amountRestaked, liquidReward); } - // @note sellVoucher function sellVoucher(uint256 claimAmount, uint256 maximumSharesToBurn) public { __sellVoucher(claimAmount, maximumSharesToBurn, false); } - // @note function sellVoucherLegacy(uint256 claimAmount, uint256 maximumSharesToBurn) public { __sellVoucher(claimAmount, maximumSharesToBurn, true); } - // @note function __sellVoucher(uint256 claimAmount, uint256 maximumSharesToBurn, bool legacy) internal { (uint256 shares, uint256 _withdrawPoolShare) = _sellVoucher(claimAmount, maximumSharesToBurn, legacy); @@ -197,23 +188,19 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I logger.logStakeUpdate(validatorId); } - // @note withdrawRewards function withdrawRewards() public { _withdrawRewards(false); } - // @note function withdrawRewardsLegacy() public { _withdrawRewards(true); } - // @note function _withdrawRewards(bool legacy) internal { uint256 rewards = _withdrawAndTransferReward(msg.sender, legacy); require(rewards >= minAmount, "Too small rewards amount"); } - // @note migrateOut function migrateOut(address user, uint256 amount) external onlyOwner { _withdrawAndTransferReward(user, false); (uint256 totalStaked, uint256 rate) = getTotalStake(user); @@ -231,23 +218,19 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I stakingLogger.logDelegatorUnstaked(validatorId, user, amount); } - // @note migrateIn function migrateIn(address user, uint256 amount) external onlyOwner { _withdrawAndTransferReward(user, false); _buyShares(amount, 0, user); } - // @note unstakeClaimTokens function unstakeClaimTokens() public { _unstakeClaimTokens(false); } - // @note function unstakeClaimTokensLegacy() public { _unstakeClaimTokens(true); } - // @note function _unstakeClaimTokens(bool legacy) internal { DelegatorUnbond memory unbond = unbonds[msg.sender]; uint256 amount = _unstakeClaimTokens(unbond, legacy); @@ -297,17 +280,14 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I /** New shares exit API */ - // @note sellVoucher_new function sellVoucher_new(uint256 claimAmount, uint256 maximumSharesToBurn) public { _sellVoucher_new(claimAmount, maximumSharesToBurn, false); } - // @note function sellVoucher_newLegacy(uint256 claimAmount, uint256 maximumSharesToBurn) public { _sellVoucher_new(claimAmount, maximumSharesToBurn, true); } - // @note function _sellVoucher_new(uint256 claimAmount, uint256 maximumSharesToBurn, bool legacy) public { (uint256 shares, uint256 _withdrawPoolShare) = _sellVoucher(claimAmount, maximumSharesToBurn, legacy); @@ -324,17 +304,14 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I stakingLogger.logStakeUpdate(validatorId); } - // @note unstakeClaimTokens function unstakeClaimTokens_new(uint256 unbondNonce) public { _unstakeClaimTokens_new(unbondNonce, false); } - // @note function unstakeClaimTokens_newLegacy(uint256 unbondNonce) public { _unstakeClaimTokens_new(unbondNonce, true); } - // @note function _unstakeClaimTokens_new(uint256 unbondNonce, bool legacy) internal { DelegatorUnbond memory unbond = unbonds_new[msg.sender][unbondNonce]; uint256 amount = _unstakeClaimTokens(unbond, legacy); @@ -355,7 +332,6 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I return _eventsHub; } - // note function _sellVoucher(uint256 claimAmount, uint256 maximumSharesToBurn, bool legacy) private returns (uint256, uint256) { // first get how much staked in total and compare to target unstake amount (uint256 totalStaked, uint256 rate) = getTotalStake(msg.sender); @@ -379,7 +355,6 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I return (shares, _withdrawPoolShare); } - // @note _unstakeClaimTokens function _unstakeClaimTokens(DelegatorUnbond memory unbond, bool legacy) private returns (uint256) { uint256 shares = unbond.shares; require( @@ -447,7 +422,6 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I return liquidRewards; } - // @note _withdrawAndTransferReward function _withdrawAndTransferReward(address user, bool legacy) private returns (uint256) { uint256 liquidRewards = _withdrawReward(user); if (liquidRewards != 0) { @@ -488,7 +462,6 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I return _amount; } - // @note _transfer function _transfer(address from, address to, uint256 value) internal { bool legacy = false; // get rewards for recipient From 26857279131f7ac614a65c8ca853de96b49a0666 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Mon, 24 Jun 2024 13:16:42 +0200 Subject: [PATCH 32/92] fix: disable slashing tests --- test/units/staking/SlashingManager.test.js | 5 +- test/units/staking/ValidatorShare.test.js | 105 +++++++++--------- .../staking/ValidatorShareLegacy.test.js | 81 ++------------ 3 files changed, 69 insertions(+), 122 deletions(-) diff --git a/test/units/staking/SlashingManager.test.js b/test/units/staking/SlashingManager.test.js index c8f4be66..8c0c2803 100644 --- a/test/units/staking/SlashingManager.test.js +++ b/test/units/staking/SlashingManager.test.js @@ -18,7 +18,8 @@ import * as chai from 'chai' chai.use(chaiAsPromised).should() const assert = chai.assert -describe('Slashing:validator', async function () { +// Slashing is currently disabled in StakeManager, so all these tests fail. +describe.skip('Slashing:validator', async function () { let stakeToken let stakeManager let slashingManager @@ -205,7 +206,7 @@ describe('Slashing:validator', async function () { }) }) }) -describe('Slashing:delegation', async function () { +describe.skip('Slashing:delegation', async function () { let stakeToken let stakeManager let slashingManager diff --git a/test/units/staking/ValidatorShare.test.js b/test/units/staking/ValidatorShare.test.js index f48d755d..abf99bbd 100644 --- a/test/units/staking/ValidatorShare.test.js +++ b/test/units/staking/ValidatorShare.test.js @@ -14,14 +14,14 @@ const ValidatorDefaultStake = new BN(toWei('100')) describe('ValidatorShare', async function () { const wei100 = toWei('100') - async function slash(slashes = [], validators = [], proposer = wallets[1], nonce = 1) { - let slashingInfoList = [] - for (const slash of slashes) { - slashingInfoList.push([parseInt(slash.validator), slash.amount, '0x0']) - } + // async function slash(slashes = [], validators = [], proposer = wallets[1], nonce = 1) { + // let slashingInfoList = [] + // for (const slash of slashes) { + // slashingInfoList.push([parseInt(slash.validator), slash.amount, '0x0']) + // } - return updateSlashedAmounts(validators, proposer, nonce, slashingInfoList, this.slashingManager) - } + // return updateSlashedAmounts(validators, proposer, nonce, slashingInfoList, this.slashingManager) + // } async function doDeploy() { await freshDeploy.call(this) @@ -578,7 +578,8 @@ describe('ValidatorShare', async function () { }) }) - describe('when Alice is slashed by 50% and then Bob purchases voucher (both buy 100 eth worth of shares)', function () { + // slashing currently disabled + describe.skip('when Alice is slashed by 50% and then Bob purchases voucher (both buy 100 eth worth of shares)', function () { before(doDeploy) describe('when Alice is slashed by 50%', function () { @@ -634,7 +635,7 @@ describe('ValidatorShare', async function () { }) }) - describe('when all tokens are slashed', function () { + describe.skip('when all tokens are slashed', function () { before(doDeploy) before(async function () { this.user = wallets[2].getAddressString() @@ -808,7 +809,8 @@ describe('ValidatorShare', async function () { }) }) - describe('when Alice sells voucher after 50% slash', function () { + // slashing currently disabled + describe.skip('when Alice sells voucher after 50% slash', function () { before(doDeployAndBuyVoucherForAliceAndBob) before('slash', async function () { await slash.call( @@ -833,7 +835,8 @@ describe('ValidatorShare', async function () { }) }) - describe('when all tokens are slashed', function () { + // slashing currently disabled + describe.skip('when all tokens are slashed', function () { before(doDeployAndBuyVoucherForAliceAndBob) before('slash', async function () { await slash.call( @@ -1000,7 +1003,8 @@ describe('ValidatorShare', async function () { }) }) - describe('when Alice is slashed by 50%', function () { + // slashing currently disabled + describe.skip('when Alice is slashed by 50%', function () { before(doDeployAndBuyVoucherForAliceAndBob) before(async function () { await slash.call( @@ -1095,7 +1099,8 @@ describe('ValidatorShare', async function () { }) }) - describe('when Alice is slashed by 50%', function () { + // slashing currently disabled + describe.skip('when Alice is slashed by 50%', function () { before(doDeployAndBuyVoucherForAliceAndBob) before(async function () { await slash.call( @@ -1158,7 +1163,7 @@ describe('ValidatorShare', async function () { const Carol = wallets[5].getChecksumAddressString() let totalDelegatorRewardsReceived - let totalSlashed + //let totalSlashed let totalStaked let totalInitialBalance let delegators = [] @@ -1186,20 +1191,20 @@ describe('ValidatorShare', async function () { }) } - function testSlash({ amount, nonce }) { - describe('Slash', function () { - it(`${amount.toString()} wei`, async function () { - await slash.call( - this, - [{ validator: this.validatorId, amount: amount }], - [this.validatorUser], - this.validatorUser, - nonce - ) - totalSlashed = totalSlashed.add(new BN(amount)) - }) - }) - } + // function testSlash({ amount, nonce }) { + // describe('Slash', function () { + // it(`${amount.toString()} wei`, async function () { + // await slash.call( + // this, + // [{ validator: this.validatorId, amount: amount }], + // [this.validatorUser], + // this.validatorUser, + // nonce + // ) + // totalSlashed = totalSlashed.add(new BN(amount)) + // }) + // }) + // } function testStake({ user, amount, label, initialBalance = new BN(0) }) { describe(`${label} buyVoucher for ${amount.toString()} wei`, function () { @@ -1207,7 +1212,7 @@ describe('ValidatorShare', async function () { totalInitialBalance = totalInitialBalance.add(initialBalance) totalStaked = totalStaked.add(new BN(amount)) - await this.stakeToken.mint(user, amount.toString()) + await this.stakeToken.mint(user, initialBalance.add(amount).toString()) const stakeTokenUser = this.stakeToken.connect(this.stakeToken.provider.getSigner(user)) await stakeTokenUser.approve(this.stakeManager.address, amount.toString()) await buyVoucher(this.validatorContract, amount.toString(), user) @@ -1279,9 +1284,8 @@ describe('ValidatorShare', async function () { assertBigNumberEquality( this.initialStakeTokenBalance .add(totalStaked.toString()) - .sub(totalReceived) - .sub(totalInitialBalance.toString()) - .sub(totalSlashed.toString()), + .sub(totalReceived), + //.sub(totalSlashed.toString()), tokensLeft ) }) @@ -1294,15 +1298,16 @@ describe('ValidatorShare', async function () { delegators = {} totalInitialBalance = new BN(0) totalStaked = new BN(0) - totalSlashed = new BN(0) + //totalSlashed = new BN(0) totalDelegatorRewardsReceived = new BN(0) this.initialStakeTokenBalance = await this.stakeToken.balanceOf(this.stakeManager.address) }) for (const step of timeline) { - if (step.slash) { - testSlash(step.slash) - } else if (step.stake) { + // if (step.slash) { + // testSlash(step.slash) + // } else + if (step.stake) { testStake(step.stake) } else if (step.checkpoints) { testCheckpoint(step.checkpoints) @@ -1334,7 +1339,8 @@ describe('ValidatorShare', async function () { ]) }) - describe('when Alice is slashed by 50% and Bob purchases voucher after', function () { + //slashing currently disabled + describe.skip('when Alice is slashed by 50% and Bob purchases voucher after', function () { describe('when 1 checkpoint passes', function () { describe('when Alice and Bob withdraw rewards after', function () { runWithdrawRewardsTest([ @@ -1366,7 +1372,7 @@ describe('ValidatorShare', async function () { }) }) - describe('when Alice is slashed after checkpoint', function () { + describe.skip('when Alice is slashed after checkpoint', function () { runWithdrawRewardsTest([ { stake: { user: Alice, label: 'Alice', amount: new BN(wei100) } }, { checkpoints: 1 }, @@ -1383,27 +1389,25 @@ describe('ValidatorShare', async function () { { checkpoints: 1 }, { liquidRewards: { user: Alice, label: 'Alice', expectedReward: toWei('4500') } }, { stake: { user: Bob, label: 'Bob', amount: new BN(toWei('500')) } }, - { slash: { amount: new BN(toWei('350')) } }, { checkpoints: 1 }, { liquidRewards: { user: Alice, label: 'Alice', expectedReward: '5785714285714285714285' } }, { liquidRewards: { user: Bob, label: 'Bob', expectedReward: '6428571428571428571428' } }, { stake: { user: Carol, label: 'Carol', amount: new BN(toWei('500')) } }, { checkpoints: 1 }, - { liquidRewards: { user: Alice, label: 'Alice', expectedReward: '6315126050420168067226' } }, - { liquidRewards: { user: Bob, label: 'Bob', expectedReward: '9075630252100840336133' } }, - { liquidRewards: { user: Carol, label: 'Carol', expectedReward: '5294117647058823529411' } }, - { slash: { amount: new BN(toWei('167')), nonce: 2 } }, + { liquidRewards: { user: Alice, label: 'Alice', expectedReward: '6535714285714285714285' } }, + { liquidRewards: { user: Bob, label: 'Bob', expectedReward: '10178571428571428571428' } }, + { liquidRewards: { user: Carol, label: 'Carol', expectedReward: '3750000000000000000000' } }, { stake: { user: Eve, label: 'Eve', amount: new BN(toWei('500')), initialBalance: new BN(1) } }, { checkpoints: 1 }, - { withdraw: { user: Alice, label: 'Alice', expectedReward: '6620779672815871910894' } }, - { withdraw: { user: Bob, label: 'Bob', expectedReward: '10603898364079359554473' } }, - { withdraw: { user: Carol, label: 'Carol', expectedReward: '8350653871015861966090' } }, - { withdraw: { user: Eve, label: 'Eve', expectedReward: '3803888419273034657649', initialBalance: new BN(1) } }, - { allRewards: { validatorReward: '6620779672815871910888', totalExpectedRewards: '35999999999999999999994' } } + { withdraw: { user: Alice, label: 'Alice', expectedReward: '7065126050420168067226' } }, + { withdraw: { user: Bob, label: 'Bob', expectedReward: '12825630252100840336133' } }, + { withdraw: { user: Carol, label: 'Carol', expectedReward: '6397058823529411764705' } }, + { withdraw: { user: Eve, label: 'Eve', expectedReward: '2647058823529411764705', initialBalance: new BN(1) } }, + { allRewards: { validatorReward: '7065126050420168067226', totalExpectedRewards: '35999999999999999999995' } } ]) }) - describe('Alice, Bob, Eve and Carol stake #2', function () { + describe.skip('Alice, Bob, Eve and Carol stake #2', function () { runWithdrawRewardsTest([ { stake: { user: Alice, label: 'Alice', amount: new BN(toWei('100')) } }, { checkpoints: 1 }, @@ -1503,7 +1507,8 @@ describe('ValidatorShare', async function () { }) }) - describe('when all tokens are slashed', function () { + // slashing is currently disabled + describe.skip('when all tokens are slashed', function () { before(doDeploy) before('slash', async function () { const amount = toWei('100') diff --git a/test/units/staking/ValidatorShareLegacy.test.js b/test/units/staking/ValidatorShareLegacy.test.js index e2c5bfae..35e96734 100644 --- a/test/units/staking/ValidatorShareLegacy.test.js +++ b/test/units/staking/ValidatorShareLegacy.test.js @@ -14,15 +14,6 @@ const ValidatorDefaultStake = new BN(toWei('100')) describe('ValidatorShareLegacy', function () { const wei100 = toWei('100') - async function slash(slashes = [], validators = [], proposer = wallets[1], nonce = 1) { - let slashingInfoList = [] - for (const slash of slashes) { - slashingInfoList.push([parseInt(slash.validator), slash.amount, '0x0']) - } - - return updateSlashedAmounts(validators, proposer, nonce, slashingInfoList, this.slashingManager) - } - async function doDeploy() { await freshDeploy.call(this) @@ -897,7 +888,6 @@ describe('ValidatorShareLegacy', function () { const Carol = wallets[5].getChecksumAddressString() let totalDelegatorRewardsReceived - let totalSlashed let totalStaked let totalInitialBalance let delegators = [] @@ -925,28 +915,13 @@ describe('ValidatorShareLegacy', function () { }) } - function testSlash({ amount, nonce }) { - describe('Slash', function () { - it(`${amount.toString()} wei`, async function () { - await slash.call( - this, - [{ validator: this.validatorId, amount: amount }], - [this.validatorUser], - this.validatorUser, - nonce - ) - totalSlashed = totalSlashed.add(new BN(amount)) - }) - }) - } - function testStake({ user, amount, label, initialBalance = new BN(0) }) { describe(`${label} buyVoucher for ${amount.toString()} wei`, function () { it(`must purchase voucher`, async function () { totalInitialBalance = totalInitialBalance.add(initialBalance) totalStaked = totalStaked.add(new BN(amount)) - await this.legacyToken.mint(user, amount.toString()) + await this.legacyToken.mint(user, initialBalance.add(amount).toString()) const legacyTokenUser = this.legacyToken.connect(this.legacyToken.provider.getSigner(user)) await legacyTokenUser.approve(this.stakeManager.address, amount.toString()) await buyVoucherLegacy(this.validatorContract, amount.toString(), user) @@ -1018,9 +993,7 @@ describe('ValidatorShareLegacy', function () { assertBigNumberEquality( this.initialStakeTokenBalance .add(totalStaked.toString()) - .sub(totalReceived) - .sub(totalInitialBalance.toString()) - .sub(totalSlashed.toString()), + .sub(totalReceived), tokensLeft ) }) @@ -1033,15 +1006,12 @@ describe('ValidatorShareLegacy', function () { delegators = {} totalInitialBalance = new BN(0) totalStaked = new BN(0) - totalSlashed = new BN(0) totalDelegatorRewardsReceived = new BN(0) this.initialStakeTokenBalance = await this.stakeToken.balanceOf(this.stakeManager.address) }) for (const step of timeline) { - if (step.slash) { - testSlash(step.slash) - } else if (step.stake) { + if (step.stake) { testStake(step.stake) } else if (step.checkpoints) { testCheckpoint(step.checkpoints) @@ -1079,53 +1049,24 @@ describe('ValidatorShareLegacy', function () { { checkpoints: 1 }, { liquidRewards: { user: Alice, label: 'Alice', expectedReward: toWei('4500') } }, { stake: { user: Bob, label: 'Bob', amount: new BN(toWei('500')) } }, - { slash: { amount: new BN(toWei('350')) } }, { checkpoints: 1 }, { liquidRewards: { user: Alice, label: 'Alice', expectedReward: '5785714285714285714285' } }, { liquidRewards: { user: Bob, label: 'Bob', expectedReward: '6428571428571428571428' } }, { stake: { user: Carol, label: 'Carol', amount: new BN(toWei('500')) } }, { checkpoints: 1 }, - { liquidRewards: { user: Alice, label: 'Alice', expectedReward: '6315126050420168067226' } }, - { liquidRewards: { user: Bob, label: 'Bob', expectedReward: '9075630252100840336133' } }, - { liquidRewards: { user: Carol, label: 'Carol', expectedReward: '5294117647058823529411' } }, - { slash: { amount: new BN(toWei('167')), nonce: 2 } }, + { liquidRewards: { user: Alice, label: 'Alice', expectedReward: '6535714285714285714285' } }, + { liquidRewards: { user: Bob, label: 'Bob', expectedReward: '10178571428571428571428' } }, + { liquidRewards: { user: Carol, label: 'Carol', expectedReward: '3750000000000000000000' } }, { stake: { user: Eve, label: 'Eve', amount: new BN(toWei('500')), initialBalance: new BN(1) } }, { checkpoints: 1 }, - { withdraw: { user: Alice, label: 'Alice', expectedReward: '6620779672815871910894' } }, - { withdraw: { user: Bob, label: 'Bob', expectedReward: '10603898364079359554473' } }, - { withdraw: { user: Carol, label: 'Carol', expectedReward: '8350653871015861966090' } }, - { withdraw: { user: Eve, label: 'Eve', expectedReward: '3803888419273034657649', initialBalance: new BN(1) } }, - { allRewards: { validatorReward: '6620779672815871910888', totalExpectedRewards: '35999999999999999999994' } } + { withdraw: { user: Alice, label: 'Alice', expectedReward: '7065126050420168067226' } }, + { withdraw: { user: Bob, label: 'Bob', expectedReward: '12825630252100840336133' } }, + { withdraw: { user: Carol, label: 'Carol', expectedReward: '6397058823529411764705' } }, + { withdraw: { user: Eve, label: 'Eve', expectedReward: '2647058823529411764705', initialBalance: new BN(1) } }, + { allRewards: { validatorReward: '7065126050420168067226', totalExpectedRewards: '35999999999999999999995' } } ]) }) - describe('Alice, Bob, Eve and Carol stake #2', function () { - runWithdrawRewardsTest([ - { stake: { user: Alice, label: 'Alice', amount: new BN(toWei('100')) } }, - { checkpoints: 1 }, - { liquidRewards: { user: Alice, label: 'Alice', expectedReward: toWei('4500') } }, - { stake: { user: Bob, label: 'Bob', amount: new BN(toWei('500')) } }, - { slash: { amount: new BN(toWei('350')) } }, - { checkpoints: 1 }, - { liquidRewards: { user: Alice, label: 'Alice', expectedReward: '5785714285714285714285' } }, - { liquidRewards: { user: Bob, label: 'Bob', expectedReward: '6428571428571428571428' } }, - { stake: { user: Carol, label: 'Carol', amount: new BN(toWei('500')) } }, - { slash: { amount: new BN(toWei('425')), nonce: 2 } }, - { checkpoints: 1 }, - { liquidRewards: { user: Alice, label: 'Alice', expectedReward: '6315126050420168067226' } }, - { liquidRewards: { user: Bob, label: 'Bob', expectedReward: '9075630252100840336133' } }, - { liquidRewards: { user: Carol, label: 'Carol', expectedReward: '5294117647058823529411' } }, - { slash: { amount: new BN(toWei('215')), nonce: 3 } }, - { stake: { user: Eve, label: 'Eve', amount: new BN(toWei('500')), initialBalance: new BN(1) } }, - { checkpoints: 1 }, - { withdraw: { user: Alice, label: 'Alice', expectedReward: '6471712628713457213871' } }, - { withdraw: { user: Bob, label: 'Bob', expectedReward: '9858563143567286069357' } }, - { withdraw: { user: Carol, label: 'Carol', expectedReward: '6859983429991714995859' } }, - { withdraw: { user: Eve, label: 'Eve', expectedReward: '6338028169014084507041', initialBalance: new BN(1) } }, - { allRewards: { validatorReward: '6471712628713457213867', totalExpectedRewards: '35999999999999999999995' } } - ]) - }) - describe('when not enough rewards', function () { before(doDeploy) From f8b9a0cb26fad5bbbaf6469a302dc6928c2c3ced Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Mon, 24 Jun 2024 13:17:06 +0200 Subject: [PATCH 33/92] fix: error on multi event failure --- test/helpers/utils.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/helpers/utils.js b/test/helpers/utils.js index 67f578cd..3089af86 100644 --- a/test/helpers/utils.js +++ b/test/helpers/utils.js @@ -481,6 +481,12 @@ export function assertInLogs(logs, eventName, eventArgs = {}) { }) if (event === undefined) { + // If this happens there are multiple events of the same name, sometimes the "correct" one is also broken (in the test) + // so we return the wrong error, in that case log all errors + if (exception.length !== 1){ + console.log("Multiple events found, unsure which is the correct one."); + console.log(exception) + } throw exception[0] } From 260ccac78ce031991e940282fd6455708fc677a1 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Tue, 25 Jun 2024 12:18:58 +0200 Subject: [PATCH 34/92] fix: properly pass return value --- contracts/staking/stakeManager/StakeManager.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 39b847b7..4111d1f4 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -465,9 +465,9 @@ contract StakeManager is function _delegationDeposit(uint256 amount, address delegator, bool legacy) internal returns (bool) { IERC20 token_ = _getToken(legacy); - token_.transferFrom(delegator, address(this), amount); + bool result = token_.transferFrom(delegator, address(this), amount); if (legacy) _convertMaticToPol(amount); - return true; + return result; } function stakeFor(address user, uint256 amount, uint256 heimdallFee, bool acceptDelegation, bytes memory signerPubkey) public onlyWhenUnlocked { From e2c430cbd27e5c1a7b3f8eb0616fe203bc4a35bf Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 25 Jun 2024 18:06:25 +0530 Subject: [PATCH 35/92] ci: skip forge tests if none --- .github/workflows/ci.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6d92583e..7e00bdd6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,9 @@ name: CI on: push: - branches: - - main + branches: [main, dev] pull_request: + branches: [main, dev] jobs: build: @@ -47,6 +47,5 @@ jobs: id: build - name: Run Forge tests - run: | - forge test -vvv + run: if test -d test/foundry && find test/foundry -name '*.sol' | grep -q .; then forge test -vvv; else echo "No .sol files found in test/foundry directory. Skipping Forge tests."; fi id: test From e2507520a1a4cdfdc5cbc3be772a7f5a512b77da Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 25 Jun 2024 22:46:19 +0530 Subject: [PATCH 36/92] new: buyVoucherWithPermit --- contracts/common/misc/IERC20Permit.sol | 19 +++++++++++++++++++ .../staking/validatorShare/ValidatorShare.sol | 18 ++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 contracts/common/misc/IERC20Permit.sol diff --git a/contracts/common/misc/IERC20Permit.sol b/contracts/common/misc/IERC20Permit.sol new file mode 100644 index 00000000..9b6d9b23 --- /dev/null +++ b/contracts/common/misc/IERC20Permit.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.5.17; + +interface IERC20Permit { + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external; + + function nonces(address owner) external view returns (uint256); + + // solhint-disable-next-line func-name-mixedcase + function DOMAIN_SEPARATOR() external view returns (bytes32); +} diff --git a/contracts/staking/validatorShare/ValidatorShare.sol b/contracts/staking/validatorShare/ValidatorShare.sol index fd77806c..64f19374 100644 --- a/contracts/staking/validatorShare/ValidatorShare.sol +++ b/contracts/staking/validatorShare/ValidatorShare.sol @@ -9,6 +9,7 @@ import {OwnableLockable} from "../../common/mixin/OwnableLockable.sol"; import {IStakeManager} from "../stakeManager/IStakeManager.sol"; import {IValidatorShare} from "./IValidatorShare.sol"; import {Initializable} from "../../common/mixin/Initializable.sol"; +import {IERC20Permit} from "./../../common/misc/IERC20Permit.sol"; contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, Initializable { struct DelegatorUnbond { @@ -112,6 +113,23 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I return _buyVoucher(_amount, _minSharesToMint, false); } + // @dev permit only available on pol token + // @dev txn fails if frontrun, use buyVoucher instead + function buyVoucherWithPermit( + uint256 _amount, + uint256 _minSharesToMint, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) public returns (uint256 amountToDeposit) { + IERC20Permit _polToken = _getOrCachePolToken(); + uint256 nonceBefore = _polToken.nonces(msg.sender); + _polToken.permit(msg.sender, address(stakeManager), _amount, deadline, v, r, s); + require(_polToken.nonces(msg.sender) == nonceBefore + 1, "Invalid permit"); + return _buyVoucher(_amount, _minSharesToMint, false); // invokes stakeManager to pull token from msg.sender + } + function buyVoucherLegacy(uint256 _amount, uint256 _minSharesToMint) public returns (uint256 amountToDeposit) { return _buyVoucher(_amount, _minSharesToMint, true); } From 74ed770d61edbe08ea01812113a32baed2f58d9f Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 25 Jun 2024 22:47:21 +0530 Subject: [PATCH 37/92] test: setup erc20permit for tests --- contracts/common/misc/EIP712.sol | 104 ++++++++++++++++++ contracts/common/tokens/ERC20Permit.sol | 77 +++++++++++++ test/helpers/artifacts.js | 1 + .../staking/ValidatorShareLegacy.test.js | 11 +- 4 files changed, 191 insertions(+), 2 deletions(-) create mode 100644 contracts/common/misc/EIP712.sol create mode 100644 contracts/common/tokens/ERC20Permit.sol diff --git a/contracts/common/misc/EIP712.sol b/contracts/common/misc/EIP712.sol new file mode 100644 index 00000000..2055cf9a --- /dev/null +++ b/contracts/common/misc/EIP712.sol @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.5.17; + +/* + meant for testing only, adapted from: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.2/contracts/utils/cryptography/EIP712.sol + modifications: + - removed `immutable` since was it introduced in solidity 0.6.5 but we have to adhere to 0.5.17 + - added chainId method since block.chainid isn't available yet + - removed `_nameFallback` & `_versionFallback` +*/ + +contract EIP712 { + /* solhint-disable var-name-mixedcase */ + // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to + // invalidate the cached domain separator if the chain id changes. + bytes32 private _CACHED_DOMAIN_SEPARATOR; + uint256 private _CACHED_CHAIN_ID; + + bytes32 private _HASHED_NAME; + bytes32 private _HASHED_VERSION; + bytes32 private _TYPE_HASH; + + /* solhint-enable var-name-mixedcase */ + + /** + * @dev Initializes the domain separator and parameter caches. + * + * The meaning of `name` and `version` is specified in + * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: + * + * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. + * - `version`: the current major version of the signing domain. + * + * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart + * contract upgrade]. + */ + constructor(string memory name, string memory version) public { + bytes32 hashedName = keccak256(bytes(name)); + bytes32 hashedVersion = keccak256(bytes(version)); + bytes32 typeHash = keccak256( + "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" + ); + _HASHED_NAME = hashedName; + _HASHED_VERSION = hashedVersion; + _CACHED_CHAIN_ID = _chainId(); + _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion); + _TYPE_HASH = typeHash; + } + + function _chainId() internal pure returns (uint chainId) { + assembly { + chainId := chainid() + } + } + + /** + * @dev Returns the domain separator for the current chain. + */ + function _domainSeparatorV4() internal view returns (bytes32) { + if (_chainId() == _CACHED_CHAIN_ID) { + return _CACHED_DOMAIN_SEPARATOR; + } else { + return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION); + } + } + + function _buildDomainSeparator( + bytes32 typeHash, + bytes32 nameHash, + bytes32 versionHash + ) private view returns (bytes32) { + return keccak256(abi.encode(typeHash, nameHash, versionHash, _chainId(), address(this))); + } + + /** + * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this + * function returns the hash of the fully encoded EIP712 message for this domain. + * + * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: + * + * ```solidity + * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( + * keccak256("Mail(address to,string contents)"), + * mailTo, + * keccak256(bytes(mailContents)) + * ))); + * address signer = ECDSA.recover(digest, signature); + * ``` + */ + function _hashTypedDataV4(bytes32 structHash) internal view returns (bytes32) { + return _toTypedDataHash(_domainSeparatorV4(), structHash); + } + + /** + * @dev Returns an Ethereum Signed Typed Data, created from a + * `domainSeparator` and a `structHash`. This produces hash corresponding + * to the one signed with the + * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] + * JSON-RPC method as part of EIP-712. + */ + function _toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { + return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); + } +} diff --git a/contracts/common/tokens/ERC20Permit.sol b/contracts/common/tokens/ERC20Permit.sol new file mode 100644 index 00000000..18a2f4a7 --- /dev/null +++ b/contracts/common/tokens/ERC20Permit.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.5.17; + +import {ECDSA} from "openzeppelin-solidity/contracts/cryptography/ECDSA.sol"; +import {TestToken} from "./TestToken.sol"; +import {EIP712} from "./../misc/EIP712.sol"; +import {IERC20Permit} from "./../misc/IERC20Permit.sol"; + +// only meant for testing, adapted from: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.2/contracts/token/ERC20/extensions/ERC20Permit.sol +// modifications: +// - check EIP712 +// - replaced custom errors with strings +// - compress v,r,s for ECDSA.recover (redundant work, only meant for testing) + +contract ERC20Permit is TestToken, IERC20Permit, EIP712 { + mapping(address => uint256) private _nonces; + + constructor( + string memory _name, + string memory _symbol, + string memory _version + ) public TestToken(_name, _symbol) EIP712(_name, _version) {} + + bytes32 private constant PERMIT_TYPEHASH = + keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); + + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) public { + if (block.timestamp > deadline) { + revert("ERC2612ExpiredSignature"); + } + + bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline)); + + bytes32 hash = _hashTypedDataV4(structHash); + + address signer = ECDSA.recover(hash, _compress(v, r, s)); + if (signer != owner) { + revert("ERC2612InvalidSigner"); + } + + _approve(owner, spender, value); + } + + function nonces(address owner) public view returns (uint256) { + return _nonces[owner]; + } + + // solhint-disable-next-line func-name-mixedcase + function DOMAIN_SEPARATOR() external view returns (bytes32) { + return _domainSeparatorV4(); + } + + function _useNonce(address owner) private returns (uint256 current) { + current = _nonces[owner]; + _nonces[owner] = current + 1; + } + + function _compress(uint8 v, bytes32 r, bytes32 s) private pure returns (bytes memory) { + bytes memory signature = new bytes(65); + + assembly { + mstore(add(signature, 0x20), r) + mstore(add(signature, 0x40), s) + mstore8(add(signature, 0x60), v) + } + + return signature; + } +} diff --git a/test/helpers/artifacts.js b/test/helpers/artifacts.js index f882fa35..9cb8d1cb 100644 --- a/test/helpers/artifacts.js +++ b/test/helpers/artifacts.js @@ -41,6 +41,7 @@ export const ERC721PredicateBurnOnly = await ethers.getContractFactory('ERC721Pr // tokens export const MaticWETH = await ethers.getContractFactory('MaticWETH') export const TestToken = await ethers.getContractFactory('TestToken') +export const ERC20Permit = await ethers.getContractFactory('ERC20Permit') export const RootERC721 = await ethers.getContractFactory('RootERC721') export const ERC721PlasmaMintable = await ethers.getContractFactory('ERC721PlasmaMintable') export const ExitNFT = await ethers.getContractFactory('ExitNFT') diff --git a/test/units/staking/ValidatorShareLegacy.test.js b/test/units/staking/ValidatorShareLegacy.test.js index 35e96734..95757993 100644 --- a/test/units/staking/ValidatorShareLegacy.test.js +++ b/test/units/staking/ValidatorShareLegacy.test.js @@ -1,4 +1,11 @@ -import {PolygonMigration, TestToken, ValidatorShare, StakingInfo, EventsHub } from '../../helpers/artifacts.js' +import { + PolygonMigration, + TestToken, + ERC20Permit, + ValidatorShare, + StakingInfo, + EventsHub +} from '../../helpers/artifacts.js' import testHelpers from '@openzeppelin/test-helpers' import { checkPoint, assertBigNumberEquality, updateSlashedAmounts, assertInTransaction } from '../../helpers/utils.js' import { wallets, freshDeploy, approveAndStake } from './deployment.js' @@ -17,7 +24,7 @@ describe('ValidatorShareLegacy', function () { async function doDeploy() { await freshDeploy.call(this) - this.stakeToken = await TestToken.deploy('POL', 'POL') + this.stakeToken = await ERC20Permit.deploy('POL', 'POL', '1.1.0') this.legacyToken = await TestToken.deploy('MATIC', 'MATIC') this.migration = await PolygonMigration.deploy(this.legacyToken.address, this.stakeToken.address) From 4042da2801a7592c63b56ef16d87449d895b7756 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 25 Jun 2024 22:50:06 +0530 Subject: [PATCH 38/92] chore: _getOrCachePolToken --- .../staking/validatorShare/ValidatorShare.sol | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/contracts/staking/validatorShare/ValidatorShare.sol b/contracts/staking/validatorShare/ValidatorShare.sol index 64f19374..51622017 100644 --- a/contracts/staking/validatorShare/ValidatorShare.sol +++ b/contracts/staking/validatorShare/ValidatorShare.sol @@ -350,7 +350,21 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I return _eventsHub; } - function _sellVoucher(uint256 claimAmount, uint256 maximumSharesToBurn, bool legacy) private returns (uint256, uint256) { + function _getOrCachePolToken() private returns (IERC20Permit) { + IERC20Permit _polToken = polToken; + if (_polToken == IERC20Permit(0x0)) { + _polToken = IERC20Permit(Registry(stakeManager.getRegistry()).contractMap(keccak256("pol"))); + require(_polToken != IERC20Permit(0x0), "unset"); + polToken = _polToken; + } + return _polToken; + } + + function _sellVoucher( + uint256 claimAmount, + uint256 maximumSharesToBurn, + bool legacy + ) private returns (uint256, uint256) { // first get how much staked in total and compare to target unstake amount (uint256 totalStaked, uint256 rate) = getTotalStake(msg.sender); require(totalStaked != 0 && totalStaked >= claimAmount, "Too much requested"); From b802ba676d1334b4d0953740af3bb4dd304b682f Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Wed, 26 Jun 2024 17:40:01 +0530 Subject: [PATCH 39/92] chore: init pol token --- contracts/staking/validatorShare/ValidatorShare.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contracts/staking/validatorShare/ValidatorShare.sol b/contracts/staking/validatorShare/ValidatorShare.sol index 51622017..9caa07d9 100644 --- a/contracts/staking/validatorShare/ValidatorShare.sol +++ b/contracts/staking/validatorShare/ValidatorShare.sol @@ -49,6 +49,8 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I EventsHub public eventsHub; + IERC20Permit public polToken; + // onlyOwner will prevent this contract from initializing, since it's owner is going to be 0x0 address function initialize( uint256 _validatorId, From 48d200d2d72f9faca4e547ac16ec26060f655ffb Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 2 Jul 2024 14:25:12 +0530 Subject: [PATCH 40/92] chore(validatorShare): disableInitializer --- contracts/common/mixin/Initializable.sol | 5 ++++- contracts/staking/validatorShare/ValidatorShare.sol | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/contracts/common/mixin/Initializable.sol b/contracts/common/mixin/Initializable.sol index d5220357..2775f03b 100644 --- a/contracts/common/mixin/Initializable.sol +++ b/contracts/common/mixin/Initializable.sol @@ -6,7 +6,10 @@ contract Initializable { modifier initializer() { require(!inited, "already inited"); inited = true; - _; } + + function _disableInitializer() internal { + inited = true; + } } diff --git a/contracts/staking/validatorShare/ValidatorShare.sol b/contracts/staking/validatorShare/ValidatorShare.sol index 9caa07d9..f66c552b 100644 --- a/contracts/staking/validatorShare/ValidatorShare.sol +++ b/contracts/staking/validatorShare/ValidatorShare.sol @@ -51,6 +51,10 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I IERC20Permit public polToken; + constructor() public { + _disableInitializer(); + } + // onlyOwner will prevent this contract from initializing, since it's owner is going to be 0x0 address function initialize( uint256 _validatorId, From 56e66bcb0c9051bdc574304a3a1a8df0c83914c3 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 2 Jul 2024 14:26:07 +0530 Subject: [PATCH 41/92] fix: solidity-rlp to 2.0.8 from floating --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 24eefeb1..10dd3475 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "mocha": "10.2.0", "nunjucks": "^3.2.0", "openzeppelin-solidity": "2.2.0", - "solidity-rlp": "^2.0.0" + "solidity-rlp": "2.0.8" }, "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^2.0.0", diff --git a/package.json b/package.json index 731f10c9..35bd3d97 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "mocha": "10.2.0", "nunjucks": "^3.2.0", "openzeppelin-solidity": "2.2.0", - "solidity-rlp": "^2.0.0" + "solidity-rlp": "2.0.8" }, "eslintConfig": { "env": { From e76df278407f3d3c1725b6f6391de8f83553967d Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 2 Jul 2024 14:26:46 +0530 Subject: [PATCH 42/92] chore(ci): run tests on feat/fix branches --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7e00bdd6..4d7d854e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,7 +2,7 @@ name: CI on: push: - branches: [main, dev] + branches: [main, dev, feat/*, fix/*] pull_request: branches: [main, dev] From 1763f1ec518f1320af29082cae62e3fb891bbbf0 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 2 Jul 2024 17:09:36 +0530 Subject: [PATCH 43/92] test: buyVoucherWithPermit --- .gitignore | 4 +- contracts/common/misc/EIP712.sol | 5 + test/helpers/artifacts.js | 2 +- test/units/staking/ValidatorShare.test.js | 170 ++++++++++++++++++++- test/units/staking/ValidatorShareHelper.js | 25 +++ test/units/staking/permitHelper.js | 66 ++++++++ 6 files changed, 266 insertions(+), 6 deletions(-) create mode 100644 test/units/staking/permitHelper.js diff --git a/.gitignore b/.gitignore index 11887e4e..d3bc16ce 100644 --- a/.gitignore +++ b/.gitignore @@ -9,8 +9,8 @@ contractAddresses.json contracts/root/predicates/TransferWithSigUtils.sol contracts/common/mixin/ChainIdMixin.sol test/helpers/marketplaceUtils.js -cache_hardhat -forge-cache +cache_hardhat/ +forge-cache/ test-bor-docker/history diff --git a/contracts/common/misc/EIP712.sol b/contracts/common/misc/EIP712.sol index 2055cf9a..4b462141 100644 --- a/contracts/common/misc/EIP712.sol +++ b/contracts/common/misc/EIP712.sol @@ -20,6 +20,7 @@ contract EIP712 { bytes32 private _HASHED_VERSION; bytes32 private _TYPE_HASH; + string private _VERSION; /* solhint-enable var-name-mixedcase */ /** @@ -47,6 +48,10 @@ contract EIP712 { _TYPE_HASH = typeHash; } + function version() external view returns (string memory) { + return _VERSION; + } + function _chainId() internal pure returns (uint chainId) { assembly { chainId := chainid() diff --git a/test/helpers/artifacts.js b/test/helpers/artifacts.js index 9cb8d1cb..0305a13c 100644 --- a/test/helpers/artifacts.js +++ b/test/helpers/artifacts.js @@ -1,5 +1,5 @@ import hardhat from 'hardhat' -const ethers = hardhat.ethers +export const ethers = hardhat.ethers export const RootChain = await ethers.getContractFactory('RootChain') export const RootChainProxy = await ethers.getContractFactory('RootChainProxy') diff --git a/test/units/staking/ValidatorShare.test.js b/test/units/staking/ValidatorShare.test.js index abf99bbd..d08ee0b3 100644 --- a/test/units/staking/ValidatorShare.test.js +++ b/test/units/staking/ValidatorShare.test.js @@ -1,8 +1,9 @@ -import { TestToken, ValidatorShare, StakingInfo, EventsHub } from '../../helpers/artifacts.js' +import ethUtils from 'ethereumjs-util' +import { TestToken, ERC20Permit, ValidatorShare, StakingInfo, EventsHub, ethers } from '../../helpers/artifacts.js' import testHelpers from '@openzeppelin/test-helpers' import { checkPoint, assertBigNumberEquality, updateSlashedAmounts, assertInTransaction } from '../../helpers/utils.js' import { wallets, freshDeploy, approveAndStake } from './deployment.js' -import { buyVoucher, sellVoucher, sellVoucherNew } from './ValidatorShareHelper.js' +import { buyVoucher, buyVoucherWithPermit, sellVoucher, sellVoucherNew } from './ValidatorShareHelper.js' const BN = testHelpers.BN const expectRevert = testHelpers.expectRevert const toWei = web3.utils.toWei @@ -26,7 +27,7 @@ describe('ValidatorShare', async function () { async function doDeploy() { await freshDeploy.call(this) - this.stakeToken = await TestToken.deploy('MATIC', 'MATIC') + this.stakeToken = await ERC20Permit.deploy('POL', 'POL', '1.1.0') await this.governance.update( this.stakeManager.address, @@ -48,6 +49,14 @@ describe('ValidatorShare', async function () { this.stakeManager.interface.encodeFunctionData('updateValidatorThreshold', [8]) ) + await this.governance.update( + this.registry.address, + this.registry.interface.encodeFunctionData('updateContractMap', [ + ethUtils.keccak256('pol'), + this.stakeToken.address + ]) + ) + // we need to increase validator id beyond foundation id, repeat 7 times for (let i = 0; i < 7; ++i) { await approveAndStake.call(this, { @@ -143,6 +152,161 @@ describe('ValidatorShare', async function () { }) } + describe('buyVoucherWithPermit', function () { + function testBuyVoucherWithPermit({ + voucherValue, + voucherValueExpected, + userTotalStaked, + totalStaked, + shares, + reward, + initialBalance + }) { + it('must buy voucher with permit', async function () { + assertBigNumberEquality(await this.stakeToken.allowance(this.user, this.stakeManager.address), 0) + this.receipt = await ( + await buyVoucherWithPermit( + this.validatorContract, + voucherValue, + this.user, + shares, + this.stakeManager.address, + this.stakeToken + ) + ).wait() + }) + + shouldBuyShares({ + voucherValueExpected, + shares, + totalStaked + }) + + shouldHaveCorrectStakes({ + userTotalStaked, + totalStaked + }) + + shouldWithdrawReward({ + initialBalance, + reward, + validatorId: '8' + }) + } + + describe('when Alice purchases voucher with permit once', function () { + deployAliceAndBob() + + before(async function () { + this.user = this.alice + await this.stakeToken + .connect(this.stakeToken.provider.getSigner(this.user)) + .approve(this.stakeManager.address, 0) + }) + + testBuyVoucherWithPermit({ + voucherValue: toWei('100'), + voucherValueExpected: toWei('100'), + userTotalStaked: toWei('100'), + totalStaked: toWei('200'), + shares: toWei('100'), + reward: '0', + initialBalance: toWei('69900') + }) + }) + + describe('when alice provides invalid permit signature', function () { + deployAliceAndBob() + + before(async function () { + this.user = this.alice + await this.stakeToken + .connect(this.stakeToken.provider.getSigner(this.user)) + .approve(this.stakeManager.address, 0) + }) + + it('reverts with incorrect spender', async function () { + assertBigNumberEquality(await this.stakeToken.allowance(this.user, this.stakeManager.address), 0) + + await expectRevert( + buyVoucherWithPermit( + this.validatorContract, + toWei('1000'), + this.user, + toWei('1000'), + this.validatorContract.address /* spender, tokens are pulled from stakeManager */, + this.stakeToken + ), + 'ERC2612InvalidSigner' + ) + }) + + it('reverts with incorrect deadline', async function () { + assertBigNumberEquality(await this.stakeToken.allowance(this.user, this.stakeManager.address), 0) + + await expectRevert( + buyVoucherWithPermit( + this.validatorContract, + toWei('1000'), + this.user, + toWei('1000'), + this.stakeManager.address, + this.stakeToken, + (await this.validatorContract.provider.getBlock('latest')).timestamp - 60 + ), + 'ERC2612ExpiredSignature' + ) + }) + }) + + describe('when locked', function () { + deployAliceAndBob() + + before(async function () { + await this.stakeManager.testLockShareContract(this.validatorId, true) + }) + + it('reverts', async function () { + await expectRevert( + buyVoucherWithPermit( + this.validatorContract, + toWei('100'), + this.alice, + toWei('100'), + this.stakeManager.address, + this.stakeToken + ), + 'locked' + ) + }) + }) + + describe('when validator unstaked', function () { + deployAliceAndBob() + before(async function () { + const stakeManagerValidator = this.stakeManager.connect( + this.stakeManager.provider.getSigner(this.validatorUser.getChecksumAddressString()) + ) + await stakeManagerValidator.unstake(this.validatorId) + await this.stakeManager.advanceEpoch(Dynasty) + }) + + it('reverts', async function () { + await expectRevert( + buyVoucherWithPermit( + this.validatorContract, + toWei('100'), + this.alice, + toWei('100'), + this.stakeManager.address, + this.stakeToken + ), + 'locked' + ) + }) + }) + }) + describe('buyVoucher', function () { function testBuyVoucher({ voucherValue, diff --git a/test/units/staking/ValidatorShareHelper.js b/test/units/staking/ValidatorShareHelper.js index 563f1030..d6e7cb66 100644 --- a/test/units/staking/ValidatorShareHelper.js +++ b/test/units/staking/ValidatorShareHelper.js @@ -1,8 +1,33 @@ +import { getPermitDigest } from './permitHelper.js' + export async function buyVoucher(validatorContract, amount, delegator, minSharesToMint) { const validatorContract_Delegator = validatorContract.connect(validatorContract.provider.getSigner(delegator)) return validatorContract_Delegator.buyVoucher(amount.toString(), minSharesToMint || 0) } +export async function buyVoucherWithPermit( + validatorContract, + amount, + delegator, + minSharesToMint, + spender, + token, + deadline +) { + const signer = validatorContract.provider.getSigner(delegator) + const validatorContract_Delegator = validatorContract.connect(signer) + + if (!deadline) deadline = (await validatorContract.provider.getBlock('latest')).timestamp + 10 + + const signature = await signer._signTypedData(...(await getPermitDigest(delegator, spender, amount, token, deadline))) + + const r = signature.slice(0, 66) + const s = '0x' + signature.slice(66, 130) + const v = '0x' + signature.slice(130, 132) + + return validatorContract_Delegator.buyVoucherWithPermit(amount.toString(), minSharesToMint || 0, deadline, v, r, s) +} + export async function sellVoucher(validatorContract, delegator, minClaimAmount, maxShares) { if (maxShares === undefined) { maxShares = await validatorContract.balanceOf(delegator) diff --git a/test/units/staking/permitHelper.js b/test/units/staking/permitHelper.js new file mode 100644 index 00000000..83e11f51 --- /dev/null +++ b/test/units/staking/permitHelper.js @@ -0,0 +1,66 @@ +import { keccak256 } from 'ethereumjs-util' +import encode from 'ethereumjs-abi' + +const PERMIT_TYPEHASH = keccak256('Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)') // 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9 + +export function getStructHash({ owner, spender, value, nonce, deadline }) { + return keccak256( + encode( + ['bytes32', 'address', 'address', 'uint256', 'uint256', 'uint256'], + [PERMIT_TYPEHASH, owner, spender, value, nonce, deadline] + ) + ) +} + +export function getTypedDataHash(DOMAIN_SEPARATOR, permitData) { + return keccak256(encode(['bytes', 'bytes32', 'bytes32'], ['\x19\x01', DOMAIN_SEPARATOR, getStructHash(permitData)])) +} + +const cache = new Map() + +export async function getPermitDigest(owner, spender, value, token, deadline) { + let { name, version } = cache.get(token.address) || {} + if (!name || !version) { + ;[name, version] = await Promise.all([token.name(), token.version()]) + cache.set(token.address, { name, version }) + } + return [ + { + name: 'POL', + version: '1.1.0', + chainId: (await token.provider._network).chainId, + verifyingContract: token.address + }, + { + Permit: [ + { + name: 'owner', + type: 'address' + }, + { + name: 'spender', + type: 'address' + }, + { + name: 'value', + type: 'uint256' + }, + { + name: 'nonce', + type: 'uint256' + }, + { + name: 'deadline', + type: 'uint256' + } + ] + }, + { + owner, + spender, + value, + nonce: await token.nonces(owner), + deadline + } + ] +} From 544a9868b535c6962c9181f1440d64f46e825019 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Sun, 7 Jul 2024 16:19:05 +0200 Subject: [PATCH 44/92] feat: rename legacy to pol --- .../staking/stakeManager/IStakeManager.sol | 27 ++++- .../staking/stakeManager/StakeManager.sol | 104 +++++++++--------- .../StakeManagerStorageExtension.sol | 2 +- .../staking/validatorShare/ValidatorShare.sol | 88 ++++++++------- 4 files changed, 124 insertions(+), 97 deletions(-) diff --git a/contracts/staking/stakeManager/IStakeManager.sol b/contracts/staking/stakeManager/IStakeManager.sol index 8e4e95bf..ccf3f7b2 100644 --- a/contracts/staking/stakeManager/IStakeManager.sol +++ b/contracts/staking/stakeManager/IStakeManager.sol @@ -17,14 +17,28 @@ contract IStakeManager { address delegator ) external returns (bool); + function transferFundsPOL( + uint256 validatorId, + uint256 amount, + address delegator + ) external returns (bool); + function delegationDeposit( uint256 validatorId, uint256 amount, address delegator ) external returns (bool); + function delegationDepositPOL( + uint256 validatorId, + uint256 amount, + address delegator + ) external returns (bool); + function unstake(uint256 validatorId) external; + function unstakePOL(uint256 validatorId) external; + function totalStakedFor(address addr) external view returns (uint256); function stakeFor( @@ -35,6 +49,14 @@ contract IStakeManager { bytes memory signerPubkey ) public; + function stakeForPOL( + address user, + uint256 amount, + uint256 heimdallFee, + bool acceptDelegation, + bytes memory signerPubkey + ) public; + function checkSignatures( uint256 blockInterval, bytes32 voteHash, @@ -73,9 +95,4 @@ contract IStakeManager { bool acceptDelegation, bytes calldata signerPubkey ) external; - - // @note MATIC POL conversion ⬇️ - - function transferFundsLegacy(uint256 validatorId, uint256 amount, address delegator) external returns (bool); - function delegationDepositLegacy(uint256 validatorId, uint256 amount, address delegator) external returns (bool); } diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 4111d1f4..523f8453 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -203,7 +203,7 @@ contract StakeManager is _unstake(validatorId, currentEpoch, false); } - function forceUnstakeLegacy(uint256 validatorId) external onlyGovernance { + function forceUnstakePOL(uint256 validatorId) external onlyGovernance { _unstake(validatorId, currentEpoch, true); } @@ -318,7 +318,7 @@ contract StakeManager is } function drain(address destination, uint256 amount) external onlyGovernance { - _transferToken(destination, amount, false); + _transferToken(destination, amount, true); } function reinitialize( @@ -335,14 +335,14 @@ contract StakeManager is validatorShareFactory = ValidatorShareFactory(_validatorShareFactory); } - function initializeLegacy( + function initializePOL( address _tokenNew, address _migration ) external onlyGovernance { - migration = IPolygonMigration(_migration); - tokenLegacy = IERC20(token); + tokenMatic = IERC20(token); token = IERC20(_tokenNew); - _convertMaticToPol(tokenLegacy.balanceOf(address(this))); + migration = IPolygonMigration(_migration); + _convertMaticToPOL(tokenMatic.balanceOf(address(this))); } /** @@ -411,8 +411,8 @@ contract StakeManager is ) external { require(msg.sender == address(this), "not allowed"); // dethrone - _transferAndTopUp(auctionUser, auctionUser, heimdallFee, 0, false); - _unstake(validatorId, currentEpoch, false); + _transferAndTopUp(auctionUser, auctionUser, heimdallFee, 0, true); + _unstake(validatorId, currentEpoch, true); uint256 newValidatorId = _stakeFor(auctionUser, auctionAmount, acceptDelegation, signerPubkey); logger.logConfirmAuction(newValidatorId, validatorId, auctionAmount); @@ -422,11 +422,11 @@ contract StakeManager is _unstake(validatorId, false); } - function unstakeLegacy(uint256 validatorId) external onlyStaker(validatorId) { + function unstakePOL(uint256 validatorId) external onlyStaker(validatorId) { _unstake(validatorId, true); } - function _unstake(uint256 validatorId, bool legacy) internal { + function _unstake(uint256 validatorId, bool pol) internal { require(validatorAuction[validatorId].amount == 0); Status status = validators[validatorId].status; @@ -437,21 +437,21 @@ contract StakeManager is ); uint256 exitEpoch = currentEpoch.add(1); // notice period - _unstake(validatorId, exitEpoch, legacy); + _unstake(validatorId, exitEpoch, pol); } function transferFunds(uint256 validatorId, uint256 amount, address delegator) external returns (bool) { return _transferFunds(validatorId, amount, delegator, false); } - function transferFundsLegacy(uint256 validatorId, uint256 amount, address delegator) external returns (bool) { + function transferFundsPOL(uint256 validatorId, uint256 amount, address delegator) external returns (bool) { return _transferFunds(validatorId, amount, delegator, true); } - function _transferFunds(uint256 validatorId, uint256 amount, address delegator, bool legacy) internal returns (bool) { + function _transferFunds(uint256 validatorId, uint256 amount, address delegator, bool pol) internal returns (bool) { require(validators[validatorId].contractAddress == msg.sender || Registry(registry).getSlashingManagerAddress() == msg.sender, "not allowed"); - if (legacy) _convertPolToMatic(amount); - IERC20 token_ = _getToken(legacy); + if (!pol) _convertPOLToMatic(amount); + IERC20 token_ = _getToken(pol); return token_.transfer(delegator, amount); } @@ -459,14 +459,14 @@ contract StakeManager is return _delegationDeposit(amount, delegator, false); } - function delegationDepositLegacy(uint256 validatorId, uint256 amount, address delegator) external onlyDelegation(validatorId) returns (bool) { + function delegationDepositPOL(uint256 validatorId, uint256 amount, address delegator) external onlyDelegation(validatorId) returns (bool) { return _delegationDeposit(amount, delegator, true); } - function _delegationDeposit(uint256 amount, address delegator, bool legacy) internal returns (bool) { - IERC20 token_ = _getToken(legacy); + function _delegationDeposit(uint256 amount, address delegator, bool pol) internal returns (bool) { + IERC20 token_ = _getToken(pol); bool result = token_.transferFrom(delegator, address(this), amount); - if (legacy) _convertMaticToPol(amount); + if (!pol) _convertMaticToPOL(amount); return result; } @@ -474,14 +474,14 @@ contract StakeManager is _stakeFor(user, amount, heimdallFee, acceptDelegation, signerPubkey, false); } - function stakeForLegacy(address user, uint256 amount, uint256 heimdallFee, bool acceptDelegation, bytes memory signerPubkey) public onlyWhenUnlocked { + function stakeForPOL(address user, uint256 amount, uint256 heimdallFee, bool acceptDelegation, bytes memory signerPubkey) public onlyWhenUnlocked { _stakeFor(user, amount, heimdallFee, acceptDelegation, signerPubkey, true); } - function _stakeFor(address user, uint256 amount, uint256 heimdallFee, bool acceptDelegation, bytes memory signerPubkey, bool legacy) internal { + function _stakeFor(address user, uint256 amount, uint256 heimdallFee, bool acceptDelegation, bytes memory signerPubkey, bool pol) internal { require(currentValidatorSetSize() < validatorThreshold, "no more slots"); require(amount >= minDeposit, "not enough deposit"); - _transferAndTopUp(user, msg.sender, heimdallFee, amount, legacy); + _transferAndTopUp(user, msg.sender, heimdallFee, amount, pol); _stakeFor(user, amount, acceptDelegation, signerPubkey); } @@ -489,11 +489,11 @@ contract StakeManager is _unstakeClaim(validatorId, false); } - function unstakeClaimLegacy(uint256 validatorId) public onlyStaker(validatorId) { + function unstakeClaimPOL(uint256 validatorId) public onlyStaker(validatorId) { _unstakeClaim(validatorId, true); } - function _unstakeClaim(uint256 validatorId, bool legacy) internal { + function _unstakeClaim(uint256 validatorId, bool pol) internal { uint256 deactivationEpoch = validators[validatorId].deactivationEpoch; // can only claim stake back after WITHDRAWAL_DELAY require( @@ -507,7 +507,7 @@ contract StakeManager is totalStaked = newTotalStaked; // claim last checkpoint reward if it was signed by validator - _liquidateRewards(validatorId, msg.sender, legacy); + _liquidateRewards(validatorId, msg.sender, pol); NFTContract.burn(validatorId); @@ -518,7 +518,7 @@ contract StakeManager is signerToValidator[validators[validatorId].signer] = INCORRECT_VALIDATOR_ID; validators[validatorId].status = Status.Unstaked; - _transferToken(msg.sender, amount, legacy); + _transferToken(msg.sender, amount, pol); logger.logUnstaked(msg.sender, validatorId, amount, newTotalStaked); } @@ -526,15 +526,15 @@ contract StakeManager is _restake(validatorId, amount, stakeRewards, false); } - function restakeLegacy(uint256 validatorId, uint256 amount, bool stakeRewards) public onlyWhenUnlocked onlyStaker(validatorId) { + function restakePOL(uint256 validatorId, uint256 amount, bool stakeRewards) public onlyWhenUnlocked onlyStaker(validatorId) { _restake(validatorId, amount, stakeRewards, true); } - function _restake(uint256 validatorId, uint256 amount, bool stakeRewards, bool legacy) internal { + function _restake(uint256 validatorId, uint256 amount, bool stakeRewards, bool pol) internal { require(validators[validatorId].deactivationEpoch == 0, "No restaking"); if (amount > 0) { - _transferTokenFrom(msg.sender, address(this), amount, legacy); + _transferTokenFrom(msg.sender, address(this), amount, pol); } _updateRewards(validatorId); @@ -558,13 +558,13 @@ contract StakeManager is _withdrawRewards(validatorId, false); } - function withdrawRewardsLegacy(uint256 validatorId) public onlyStaker(validatorId) { + function withdrawRewardsPOL(uint256 validatorId) public onlyStaker(validatorId) { _withdrawRewards(validatorId, true); } - function _withdrawRewards(uint256 validatorId, bool legacy) internal { + function _withdrawRewards(uint256 validatorId, bool pol) internal { _updateRewards(validatorId); - _liquidateRewards(validatorId, msg.sender, legacy); + _liquidateRewards(validatorId, msg.sender, pol); } function migrateDelegation( @@ -1111,7 +1111,7 @@ contract StakeManager is return validatorId; } - function _unstake(uint256 validatorId, uint256 exitEpoch, bool legacy) internal { + function _unstake(uint256 validatorId, uint256 exitEpoch, bool pol) internal { // TODO: if validators unstake and slashed to 0, he will be forced to unstake again // must think how to handle it correctly _updateRewards(validatorId); @@ -1130,7 +1130,7 @@ contract StakeManager is } _removeSigner(validators[validatorId].signer); - _liquidateRewards(validatorId, validator, legacy); + _liquidateRewards(validatorId, validator, pol); uint256 targetEpoch = exitEpoch <= currentEpoch ? 0 : exitEpoch; updateTimeline(-(int256(amount) + delegationAmount), -1, targetEpoch); @@ -1150,30 +1150,30 @@ contract StakeManager is currentEpoch = nextEpoch; } - function _liquidateRewards(uint256 validatorId, address validatorUser, bool legacy) private { + function _liquidateRewards(uint256 validatorId, address validatorUser, bool pol) private { uint256 reward = validators[validatorId].reward.sub(INITIALIZED_AMOUNT); totalRewardsLiquidated = totalRewardsLiquidated.add(reward); validators[validatorId].reward = INITIALIZED_AMOUNT; - _transferToken(validatorUser, reward, legacy); + _transferToken(validatorUser, reward, pol); logger.logClaimRewards(validatorId, reward, totalRewardsLiquidated); } - function _transferToken(address destination, uint256 amount, bool legacy) private { - if (legacy) _convertPolToMatic(amount); - IERC20 token_ = _getToken(legacy); + function _transferToken(address destination, uint256 amount, bool pol) private { + if (!pol) _convertPOLToMatic(amount); + IERC20 token_ = _getToken(pol); require(token_.transfer(destination, amount), "transfer failed"); } // Do not use this function to transfer from self. - function _transferTokenFrom(address from, address destination, uint256 amount, bool legacy) private { - IERC20 token_ = _getToken(legacy); + function _transferTokenFrom(address from, address destination, uint256 amount, bool pol) private { + IERC20 token_ = _getToken(pol); require(token_.transferFrom(from, destination, amount), "transfer from failed"); - if (legacy && destination == address(this)) _convertMaticToPol(amount); + if (!pol && destination == address(this)) _convertMaticToPOL(amount); } - function _transferAndTopUp(address user, address from, uint256 fee, uint256 additionalAmount, bool legacy) private { + function _transferAndTopUp(address user, address from, uint256 fee, uint256 additionalAmount, bool pol) private { require(fee >= minHeimdallFee, "fee too small"); - _transferTokenFrom(from, address(this), fee.add(additionalAmount), legacy); + _transferTokenFrom(from, address(this), fee.add(additionalAmount), pol); totalHeimdallFee = totalHeimdallFee.add(fee); logger.logTopUpFee(user, fee); } @@ -1213,23 +1213,23 @@ contract StakeManager is signers.length = totalSigners - 1; } - function convertMaticToPol(uint256 amount) external onlyGovernance { - _convertMaticToPol(amount); + function convertMaticToPOL(uint256 amount) external onlyGovernance { + _convertMaticToPOL(amount); } - function _convertMaticToPol(uint256 amount) internal { - require(tokenLegacy.balanceOf(address(this)) >= amount, "Lacking MATIC"); - tokenLegacy.approve(address(migration), amount); + function _convertMaticToPOL(uint256 amount) internal { + require(tokenMatic.balanceOf(address(this)) >= amount, "Lacking MATIC"); + tokenMatic.approve(address(migration), amount); migration.migrate(amount); } - function _convertPolToMatic(uint256 amount) internal { + function _convertPOLToMatic(uint256 amount) internal { require(token.balanceOf(address(this)) >= amount, "Lacking POL"); token.approve(address(migration), amount); migration.unmigrate(amount); } - function _getToken(bool legacy) internal view returns (IERC20 token_) { - token_ = !legacy ? token : tokenLegacy; + function _getToken(bool pol) internal view returns (IERC20 token_) { + token_ = pol ? token : tokenMatic; } } diff --git a/contracts/staking/stakeManager/StakeManagerStorageExtension.sol b/contracts/staking/stakeManager/StakeManagerStorageExtension.sol index 68e715a8..adf715f8 100644 --- a/contracts/staking/stakeManager/StakeManagerStorageExtension.sol +++ b/contracts/staking/stakeManager/StakeManagerStorageExtension.sol @@ -18,6 +18,6 @@ contract StakeManagerStorageExtension { // increase / decrease value for faster or slower checkpoints, 0 - 100% uint256 public checkpointRewardDelta; - IERC20 public tokenLegacy; + IERC20 public tokenMatic; IPolygonMigration public migration; } diff --git a/contracts/staking/validatorShare/ValidatorShare.sol b/contracts/staking/validatorShare/ValidatorShare.sol index f66c552b..7665f67b 100644 --- a/contracts/staking/validatorShare/ValidatorShare.sol +++ b/contracts/staking/validatorShare/ValidatorShare.sol @@ -129,24 +129,24 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I bytes32 r, bytes32 s ) public returns (uint256 amountToDeposit) { - IERC20Permit _polToken = _getOrCachePolToken(); + IERC20Permit _polToken = _getOrCachePOLToken(); uint256 nonceBefore = _polToken.nonces(msg.sender); _polToken.permit(msg.sender, address(stakeManager), _amount, deadline, v, r, s); require(_polToken.nonces(msg.sender) == nonceBefore + 1, "Invalid permit"); - return _buyVoucher(_amount, _minSharesToMint, false); // invokes stakeManager to pull token from msg.sender + return _buyVoucher(_amount, _minSharesToMint, true); // invokes stakeManager to pull token from msg.sender } - function buyVoucherLegacy(uint256 _amount, uint256 _minSharesToMint) public returns (uint256 amountToDeposit) { + function buyVoucherPOL(uint256 _amount, uint256 _minSharesToMint) public returns (uint256 amountToDeposit) { return _buyVoucher(_amount, _minSharesToMint, true); } - function _buyVoucher(uint256 _amount, uint256 _minSharesToMint, bool legacy) internal returns (uint256 amountToDeposit) { - _withdrawAndTransferReward(msg.sender, legacy); + function _buyVoucher(uint256 _amount, uint256 _minSharesToMint, bool pol) internal returns (uint256 amountToDeposit) { + _withdrawAndTransferReward(msg.sender, pol); amountToDeposit = _buyShares(_amount, _minSharesToMint, msg.sender); require( - legacy - ? stakeManager.delegationDepositLegacy(validatorId, amountToDeposit, msg.sender) + pol + ? stakeManager.delegationDepositPOL(validatorId, amountToDeposit, msg.sender) : stakeManager.delegationDeposit(validatorId, amountToDeposit, msg.sender), "deposit failed" ); @@ -158,11 +158,11 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I return _restake(false); } - function restakeLegacy() public returns (uint256, uint256) { + function restakePOL() public returns (uint256, uint256) { return _restake(true); } - function _restake(bool legacy) public returns (uint256, uint256) { + function _restake(bool pol) public returns (uint256, uint256) { address user = msg.sender; uint256 liquidReward = _withdrawReward(user); uint256 amountRestaked; @@ -175,8 +175,8 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I if (liquidReward > amountRestaked) { // return change to the user require( - legacy - ? stakeManager.transferFundsLegacy(validatorId, liquidReward - amountRestaked, user) + pol + ? stakeManager.transferFundsPOL(validatorId, liquidReward - amountRestaked, user) : stakeManager.transferFunds(validatorId, liquidReward - amountRestaked, user), "Insufficent rewards" ); @@ -194,12 +194,12 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I __sellVoucher(claimAmount, maximumSharesToBurn, false); } - function sellVoucherLegacy(uint256 claimAmount, uint256 maximumSharesToBurn) public { + function sellVoucherPOL(uint256 claimAmount, uint256 maximumSharesToBurn) public { __sellVoucher(claimAmount, maximumSharesToBurn, true); } - function __sellVoucher(uint256 claimAmount, uint256 maximumSharesToBurn, bool legacy) internal { - (uint256 shares, uint256 _withdrawPoolShare) = _sellVoucher(claimAmount, maximumSharesToBurn, legacy); + function __sellVoucher(uint256 claimAmount, uint256 maximumSharesToBurn, bool pol) internal { + (uint256 shares, uint256 _withdrawPoolShare) = _sellVoucher(claimAmount, maximumSharesToBurn, pol); DelegatorUnbond memory unbond = unbonds[msg.sender]; unbond.shares = unbond.shares.add(_withdrawPoolShare); @@ -216,17 +216,17 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I _withdrawRewards(false); } - function withdrawRewardsLegacy() public { + function withdrawRewardsPOL() public { _withdrawRewards(true); } - function _withdrawRewards(bool legacy) internal { - uint256 rewards = _withdrawAndTransferReward(msg.sender, legacy); + function _withdrawRewards(bool pol) internal { + uint256 rewards = _withdrawAndTransferReward(msg.sender, pol); require(rewards >= minAmount, "Too small rewards amount"); } function migrateOut(address user, uint256 amount) external onlyOwner { - _withdrawAndTransferReward(user, false); + _withdrawAndTransferReward(user, true); (uint256 totalStaked, uint256 rate) = getTotalStake(user); require(totalStaked >= amount, "Migrating too much"); @@ -243,7 +243,7 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I } function migrateIn(address user, uint256 amount) external onlyOwner { - _withdrawAndTransferReward(user, false); + _withdrawAndTransferReward(user, true); _buyShares(amount, 0, user); } @@ -251,13 +251,13 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I _unstakeClaimTokens(false); } - function unstakeClaimTokensLegacy() public { + function unstakeClaimTokensPOL() public { _unstakeClaimTokens(true); } - function _unstakeClaimTokens(bool legacy) internal { + function _unstakeClaimTokens(bool pol) internal { DelegatorUnbond memory unbond = unbonds[msg.sender]; - uint256 amount = _unstakeClaimTokens(unbond, legacy); + uint256 amount = _unstakeClaimTokens(unbond, pol); delete unbonds[msg.sender]; stakingLogger.logDelegatorUnstaked(validatorId, msg.sender, amount); } @@ -308,12 +308,12 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I _sellVoucher_new(claimAmount, maximumSharesToBurn, false); } - function sellVoucher_newLegacy(uint256 claimAmount, uint256 maximumSharesToBurn) public { + function sellVoucher_newPOL(uint256 claimAmount, uint256 maximumSharesToBurn) public { _sellVoucher_new(claimAmount, maximumSharesToBurn, true); } - function _sellVoucher_new(uint256 claimAmount, uint256 maximumSharesToBurn, bool legacy) public { - (uint256 shares, uint256 _withdrawPoolShare) = _sellVoucher(claimAmount, maximumSharesToBurn, legacy); + function _sellVoucher_new(uint256 claimAmount, uint256 maximumSharesToBurn, bool pol) public { + (uint256 shares, uint256 _withdrawPoolShare) = _sellVoucher(claimAmount, maximumSharesToBurn, pol); uint256 unbondNonce = unbondNonces[msg.sender].add(1); @@ -332,13 +332,13 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I _unstakeClaimTokens_new(unbondNonce, false); } - function unstakeClaimTokens_newLegacy(uint256 unbondNonce) public { + function unstakeClaimTokens_newPOL(uint256 unbondNonce) public { _unstakeClaimTokens_new(unbondNonce, true); } - function _unstakeClaimTokens_new(uint256 unbondNonce, bool legacy) internal { + function _unstakeClaimTokens_new(uint256 unbondNonce, bool pol) internal { DelegatorUnbond memory unbond = unbonds_new[msg.sender][unbondNonce]; - uint256 amount = _unstakeClaimTokens(unbond, legacy); + uint256 amount = _unstakeClaimTokens(unbond, pol); delete unbonds_new[msg.sender][unbondNonce]; _getOrCacheEventsHub().logDelegatorUnstakedWithId(validatorId, msg.sender, amount, unbondNonce); } @@ -356,7 +356,7 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I return _eventsHub; } - function _getOrCachePolToken() private returns (IERC20Permit) { + function _getOrCachePOLToken() private returns (IERC20Permit) { IERC20Permit _polToken = polToken; if (_polToken == IERC20Permit(0x0)) { _polToken = IERC20Permit(Registry(stakeManager.getRegistry()).contractMap(keccak256("pol"))); @@ -369,7 +369,7 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I function _sellVoucher( uint256 claimAmount, uint256 maximumSharesToBurn, - bool legacy + bool pol ) private returns (uint256, uint256) { // first get how much staked in total and compare to target unstake amount (uint256 totalStaked, uint256 rate) = getTotalStake(msg.sender); @@ -380,7 +380,7 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I uint256 shares = claimAmount.mul(precision).div(rate); require(shares <= maximumSharesToBurn, "too much slippage"); - _withdrawAndTransferReward(msg.sender, legacy); + _withdrawAndTransferReward(msg.sender, pol); _burn(msg.sender, shares); stakeManager.updateValidatorState(validatorId, -int256(claimAmount)); @@ -393,7 +393,7 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I return (shares, _withdrawPoolShare); } - function _unstakeClaimTokens(DelegatorUnbond memory unbond, bool legacy) private returns (uint256) { + function _unstakeClaimTokens(DelegatorUnbond memory unbond, bool pol) private returns (uint256) { uint256 shares = unbond.shares; require( unbond.withdrawEpoch.add(stakeManager.withdrawalDelay()) <= stakeManager.epoch() && shares > 0, @@ -405,7 +405,7 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I withdrawPool = withdrawPool.sub(_amount); require( - legacy ? stakeManager.transferFundsLegacy(validatorId, _amount, msg.sender) : stakeManager.transferFunds(validatorId, _amount, msg.sender), + pol ? stakeManager.transferFundsPOL(validatorId, _amount, msg.sender) : stakeManager.transferFunds(validatorId, _amount, msg.sender), "Insufficent rewards" ); @@ -460,11 +460,11 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I return liquidRewards; } - function _withdrawAndTransferReward(address user, bool legacy) private returns (uint256) { + function _withdrawAndTransferReward(address user, bool pol) private returns (uint256) { uint256 liquidRewards = _withdrawReward(user); if (liquidRewards != 0) { require( - legacy ? stakeManager.transferFundsLegacy(validatorId, liquidRewards, user) : stakeManager.transferFunds(validatorId, liquidRewards, user), + pol ? stakeManager.transferFundsPOL(validatorId, liquidRewards, user) : stakeManager.transferFunds(validatorId, liquidRewards, user), "Insufficent rewards" ); stakingLogger.logDelegatorClaimRewards(validatorId, user, liquidRewards); @@ -500,12 +500,22 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I return _amount; } - function _transfer(address from, address to, uint256 value) internal { - bool legacy = false; + function transferPOL(address to, uint256 value) public returns (bool) { + _transfer(to, value, true); + return true; + } + + function transfer(address to, uint256 value) public returns (bool) { + _transfer(to, value, false); + return true; + } + + function _transfer(address to, uint256 value, bool pol) internal { + address from = msg.sender; // get rewards for recipient - _withdrawAndTransferReward(to, legacy); + _withdrawAndTransferReward(to, pol); // convert rewards to shares - _withdrawAndTransferReward(from, legacy); + _withdrawAndTransferReward(from, pol); // move shares to recipient super._transfer(from, to, value); _getOrCacheEventsHub().logSharesTransfer(validatorId, from, to, value); From 55e25fa2cb2bd7736bd224ff97f5db67eac262e7 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Sun, 7 Jul 2024 16:27:23 +0200 Subject: [PATCH 45/92] fix: tests after rename --- test/helpers/deployer.js | 47 ++- test/units/root/RootChain.test.js | 8 +- test/units/staking/DrainStakeManager.test.js | 34 +- test/units/staking/ValidatorShare.test.js | 139 ++++----- test/units/staking/ValidatorShareHelper.js | 12 +- ...gacy.test.js => ValidatorSharePol.test.js} | 295 +++++++++--------- test/units/staking/deployment.js | 25 +- .../stakeManager/StakeManager.Staking.js | 42 ++- ...ngLegacy.js => StakeManager.StakingPol.js} | 176 +++++------ .../staking/stakeManager/StakeManager.test.js | 133 ++++---- 10 files changed, 464 insertions(+), 447 deletions(-) rename test/units/staking/{ValidatorShareLegacy.test.js => ValidatorSharePol.test.js} (84%) rename test/units/staking/stakeManager/{StakeManager.StakingLegacy.js => StakeManager.StakingPol.js} (84%) diff --git a/test/helpers/deployer.js b/test/helpers/deployer.js index c6e2f0e3..c746a2fa 100644 --- a/test/helpers/deployer.js +++ b/test/helpers/deployer.js @@ -52,7 +52,7 @@ class Deployer { ]) ) - this.stakeManager = await contractFactories.StakeManager.attach(stakeManagerProxy.address) + this.stakeManager = contractFactories.StakeManager.attach(stakeManagerProxy.address) // TODO cannot alter functions like we used to here, replace usage with actual impl like below // this.buildStakeManagerObject(this.stakeManager, this.governance) await this.governance.update( @@ -84,7 +84,7 @@ class Deployer { return _contracts } - async deployStakeManager(wallets, legacy = false) { + async deployStakeManager(wallets, pol = false) { this.governance = await this.deployGovernance() this.registry = await contractFactories.Registry.deploy(this.governance.address) @@ -93,15 +93,7 @@ class Deployer { this.validatorShare = await contractFactories.ValidatorShare.deploy() this.rootChain = await this.deployRootChain() this.stakingInfo = await contractFactories.StakingInfo.deploy(this.registry.address) - - let token - if (legacy){ - this.legacyToken = await contractFactories.TestToken.deploy('Legacy Token', 'LEG') - token = this.legacyToken - } else { - this.stakeToken = await contractFactories.TestToken.deploy('Stake Token', 'STAKE') - token = this.stakeToken - } + this.stakeToken = await contractFactories.TestToken.deploy('Stake Token', 'STAKE') this.stakingNFT = await contractFactories.StakingNFT.deploy('Matic Validator', 'MV') @@ -114,7 +106,7 @@ class Deployer { stakeManager.interface.encodeFunctionData('initialize', [ this.registry.address, rootChainOwner.getAddressString(), - token.address, + this.stakeToken.address, this.stakingNFT.address, this.stakingInfo.address, this.validatorShareFactory.address, @@ -124,40 +116,43 @@ class Deployer { ]) ) - this.stakeManager = await contractFactories.StakeManagerTestable.attach(proxy.address) + this.stakeManager = contractFactories.StakeManagerTestable.attach(proxy.address) this.slashingManager = await contractFactories.SlashingManager.deploy( this.registry.address, this.stakingInfo.address, 'heimdall-P5rXwg' ) - if (legacy){ - await token.mint(this.stakeManager.address, web3.utils.toWei('10000000')) + await this.stakingNFT.transferOwnership(this.stakeManager.address) + await this.updateContractMap(ethUtils.keccak256('stakeManager'), this.stakeManager.address) + await this.updateContractMap(ethUtils.keccak256('validatorShare'), this.validatorShare.address) + await this.updateContractMap(ethUtils.keccak256('slashingManager'), this.slashingManager.address) + + await this.stakeToken.mint(this.stakeManager.address, web3.utils.toWei('10000000')) - this.stakeToken = await contractFactories.TestToken.deploy('POL', 'POL') + if (pol){ + this.polToken = await contractFactories.ERC20Permit.deploy('POL', 'POL', '1.1.0') - this.migration = await contractFactories.PolygonMigration.deploy(this.legacyToken.address, this.stakeToken.address) + this.migration = await contractFactories.PolygonMigration.deploy(this.stakeToken.address, this.polToken.address) await this.stakeToken.mint(this.migration.address, web3.utils.toWei('50000000')) - await this.legacyToken.mint(this.migration.address, web3.utils.toWei('50000000')) + await this.polToken.mint(this.migration.address, web3.utils.toWei('50000000')) await this.governance.update( this.stakeManager.address, - this.stakeManager.interface.encodeFunctionData('initializeLegacy', [this.stakeToken.address, this.migration.address]) + this.stakeManager.interface.encodeFunctionData('initializePOL', [this.polToken.address, this.migration.address]) ) - } - - await this.stakingNFT.transferOwnership(this.stakeManager.address) - await this.updateContractMap(ethUtils.keccak256('stakeManager'), this.stakeManager.address) - await this.updateContractMap(ethUtils.keccak256('validatorShare'), this.validatorShare.address) - await this.updateContractMap(ethUtils.keccak256('slashingManager'), this.slashingManager.address) + + await this.updateContractMap(ethUtils.keccak256('pol'), this.polToken.address) + } + let _contracts = { rootChainOwner: rootChainOwner, registry: this.registry, rootChain: this.rootChain, stakeManager: this.stakeManager, stakeToken: this.stakeToken, - legacyToken: this.legacyToken, + polToken: this.polToken, slashingManager: this.slashingManager, stakingInfo: this.stakingInfo, governance: this.governance, diff --git a/test/units/root/RootChain.test.js b/test/units/root/RootChain.test.js index 1a1c97be..422c46fe 100644 --- a/test/units/root/RootChain.test.js +++ b/test/units/root/RootChain.test.js @@ -44,15 +44,11 @@ describe('RootChain', async function (accounts) { }) async function freshDeploy() { - const contracts = await deployer.deployStakeManager(wallets) + const contracts = await deployer.deployStakeManager(wallets, true) governance = contracts.governance rootChain = contracts.rootChain stakeManager = contracts.stakeManager - stakeToken = await TestToken.deploy('Stake Token', 'STAKE') - await contracts.governance.update( - stakeManager.address, - stakeManager.interface.encodeFunctionData('setStakingToken', [stakeToken.address]) - ) + stakeToken = contracts.stakeToken await stakeManager.changeRootChain(rootChain.address) await contracts.governance.update( stakeManager.address, diff --git a/test/units/staking/DrainStakeManager.test.js b/test/units/staking/DrainStakeManager.test.js index cffcfccf..fc1a75d5 100644 --- a/test/units/staking/DrainStakeManager.test.js +++ b/test/units/staking/DrainStakeManager.test.js @@ -2,6 +2,7 @@ import chai, { assert } from 'chai' import chaiAsPromised from 'chai-as-promised' +import { BN } from '@openzeppelin/test-helpers' import { DrainStakeManager } from '../../helpers/artifacts.js' @@ -12,21 +13,25 @@ import { generateFirstWallets, mnemonics } from '../../helpers/wallets.js' chai.use(chaiAsPromised).should() -describe('DrainStakeManager', async function (accounts) { - accounts = await ethers.getSigners() - accounts = accounts.map((account) => { - return account.address +// todo: is this even needed anymore? +describe('DrainStakeManager', function (accounts) { + let owner + before(async function() { + accounts = await ethers.getSigners() + accounts = accounts.map((account) => { + return account.address + }) + owner = accounts[0] }) - - const owner = accounts[0] - describe('Upgrade and drain staking contract', async function () { + + describe('Upgrade and drain staking contract', function () { before(async function () { this.wallets = generateFirstWallets(mnemonics, 10) - let contracts = await deployer.deployStakeManager(this.wallets) + let contracts = await deployer.deployStakeManager(this.wallets, true) this.governance = contracts.governance - this.stakeToken = contracts.stakeToken + this.polToken = contracts.polToken this.stakeManager = contracts.stakeManager this.proxy = contracts.stakeManagerProxy this.stakeManagerImpl = contracts.stakeManagerImpl @@ -36,9 +41,10 @@ describe('DrainStakeManager', async function (accounts) { }) it('must have some tokens', async function () { + const initalAmount = web3.utils.toWei('10000000') const amount = web3.utils.toWei('90000') - await this.stakeToken.mint(this.stakeManager.address, amount) - ;(await this.stakeToken.balanceOf(this.stakeManager.address)).toString().should.be.equal(amount.toString()) + await this.polToken.mint(this.stakeManager.address, amount) + ;(await this.polToken.balanceOf(this.stakeManager.address)).toString().should.be.equal(BN(amount).add(BN(initalAmount)).toString()) }) it('must lock stake manager', async function () { @@ -60,7 +66,7 @@ describe('DrainStakeManager', async function (accounts) { }) it('must fail draining when not drained owner', async function () { - const balance = await this.stakeToken.balanceOf(this.stakeManager.address) + const balance = await this.polToken.balanceOf(this.stakeManager.address) try { await this.stakeManagerDrainable.drain(owner, balance) assert.fail('Funds should not be drained') @@ -70,10 +76,10 @@ describe('DrainStakeManager', async function (accounts) { }) it('must drain all funds when drained by owner (Gnosis safe)', async function () { - const balance = await this.stakeToken.balanceOf(this.stakeManager.address) + const balance = await this.polToken.balanceOf(this.stakeManager.address) const data = this.stakeManagerDrainable.interface.encodeFunctionData('drain', [owner, balance.toString()]) await execSafe(this.gSafe, this.stakeManager.address, data, [accounts[1], accounts[2]]) - assert.equal((await this.stakeToken.balanceOf(this.stakeManager.address)).toString(), '0') + assert.equal((await this.polToken.balanceOf(this.stakeManager.address)).toString(), '0') }) it('must swap back to normal implementaion', async function () { diff --git a/test/units/staking/ValidatorShare.test.js b/test/units/staking/ValidatorShare.test.js index d08ee0b3..375bfebd 100644 --- a/test/units/staking/ValidatorShare.test.js +++ b/test/units/staking/ValidatorShare.test.js @@ -1,7 +1,7 @@ import ethUtils from 'ethereumjs-util' import { TestToken, ERC20Permit, ValidatorShare, StakingInfo, EventsHub, ethers } from '../../helpers/artifacts.js' import testHelpers from '@openzeppelin/test-helpers' -import { checkPoint, assertBigNumberEquality, updateSlashedAmounts, assertInTransaction } from '../../helpers/utils.js' +import { checkPoint, assertBigNumberEquality, assertInTransaction } from '../../helpers/utils.js' import { wallets, freshDeploy, approveAndStake } from './deployment.js' import { buyVoucher, buyVoucherWithPermit, sellVoucher, sellVoucherNew } from './ValidatorShareHelper.js' const BN = testHelpers.BN @@ -25,16 +25,7 @@ describe('ValidatorShare', async function () { // } async function doDeploy() { - await freshDeploy.call(this) - - this.stakeToken = await ERC20Permit.deploy('POL', 'POL', '1.1.0') - - await this.governance.update( - this.stakeManager.address, - this.stakeManager.interface.encodeFunctionData('setStakingToken', [this.stakeToken.address]) - ) - - await this.stakeToken.mint(this.stakeManager.address, toWei('10000000')) + await freshDeploy.call(this, true) this.validatorId = '8' this.validatorUser = wallets[0] @@ -49,14 +40,6 @@ describe('ValidatorShare', async function () { this.stakeManager.interface.encodeFunctionData('updateValidatorThreshold', [8]) ) - await this.governance.update( - this.registry.address, - this.registry.interface.encodeFunctionData('updateContractMap', [ - ethUtils.keccak256('pol'), - this.stakeToken.address - ]) - ) - // we need to increase validator id beyond foundation id, repeat 7 times for (let i = 0; i < 7; ++i) { await approveAndStake.call(this, { @@ -85,7 +68,7 @@ describe('ValidatorShare', async function () { await this.stakeManager.forceFinalizeCommit() let validator = await this.stakeManager.validators(this.validatorId) - this.validatorContract = await ValidatorShare.attach(validator.contractAddress) + this.validatorContract = ValidatorShare.attach(validator.contractAddress) } describe('locking', function () { @@ -163,7 +146,7 @@ describe('ValidatorShare', async function () { initialBalance }) { it('must buy voucher with permit', async function () { - assertBigNumberEquality(await this.stakeToken.allowance(this.user, this.stakeManager.address), 0) + assertBigNumberEquality(await this.polToken.allowance(this.user, this.stakeManager.address), 0) this.receipt = await ( await buyVoucherWithPermit( this.validatorContract, @@ -171,7 +154,7 @@ describe('ValidatorShare', async function () { this.user, shares, this.stakeManager.address, - this.stakeToken + this.polToken ) ).wait() }) @@ -190,7 +173,8 @@ describe('ValidatorShare', async function () { shouldWithdrawReward({ initialBalance, reward, - validatorId: '8' + validatorId: '8', + pol: true }) } @@ -199,10 +183,10 @@ describe('ValidatorShare', async function () { before(async function () { this.user = this.alice - await this.stakeToken - .connect(this.stakeToken.provider.getSigner(this.user)) + await this.polToken + .connect(this.polToken.provider.getSigner(this.user)) .approve(this.stakeManager.address, 0) - }) + }) testBuyVoucherWithPermit({ voucherValue: toWei('100'), @@ -211,7 +195,7 @@ describe('ValidatorShare', async function () { totalStaked: toWei('200'), shares: toWei('100'), reward: '0', - initialBalance: toWei('69900') + initialBalance: toWei('705') }) }) @@ -220,13 +204,13 @@ describe('ValidatorShare', async function () { before(async function () { this.user = this.alice - await this.stakeToken - .connect(this.stakeToken.provider.getSigner(this.user)) + await this.polToken + .connect(this.polToken.provider.getSigner(this.user)) .approve(this.stakeManager.address, 0) }) it('reverts with incorrect spender', async function () { - assertBigNumberEquality(await this.stakeToken.allowance(this.user, this.stakeManager.address), 0) + assertBigNumberEquality(await this.polToken.allowance(this.user, this.stakeManager.address), 0) await expectRevert( buyVoucherWithPermit( @@ -235,14 +219,14 @@ describe('ValidatorShare', async function () { this.user, toWei('1000'), this.validatorContract.address /* spender, tokens are pulled from stakeManager */, - this.stakeToken + this.polToken ), 'ERC2612InvalidSigner' ) }) it('reverts with incorrect deadline', async function () { - assertBigNumberEquality(await this.stakeToken.allowance(this.user, this.stakeManager.address), 0) + assertBigNumberEquality(await this.polToken.allowance(this.user, this.stakeManager.address), 0) await expectRevert( buyVoucherWithPermit( @@ -251,7 +235,7 @@ describe('ValidatorShare', async function () { this.user, toWei('1000'), this.stakeManager.address, - this.stakeToken, + this.polToken, (await this.validatorContract.provider.getBlock('latest')).timestamp - 60 ), 'ERC2612ExpiredSignature' @@ -274,7 +258,7 @@ describe('ValidatorShare', async function () { this.alice, toWei('100'), this.stakeManager.address, - this.stakeToken + this.polToken ), 'locked' ) @@ -299,7 +283,7 @@ describe('ValidatorShare', async function () { this.alice, toWei('100'), this.stakeManager.address, - this.stakeToken + this.polToken ), 'locked' ) @@ -353,7 +337,7 @@ describe('ValidatorShare', async function () { totalStaked: toWei('200'), shares: toWei('100'), reward: '0', - initialBalance: toWei('69900') + initialBalance: toWei('70705') }) }) @@ -371,7 +355,7 @@ describe('ValidatorShare', async function () { totalStaked: toWei('200'), shares: toWei('100'), reward: '0', - initialBalance: toWei('69900') + initialBalance: toWei('70705') }) }) @@ -423,7 +407,7 @@ describe('ValidatorShare', async function () { totalStaked: toWei('200'), shares: toWei('100'), reward: '0', - initialBalance: toWei('69900') + initialBalance: toWei('70705') }) }) @@ -435,7 +419,7 @@ describe('ValidatorShare', async function () { totalStaked: toWei('350'), shares: toWei('150'), reward: '0', - initialBalance: toWei('69750') + initialBalance: toWei('70555') }) }) @@ -447,7 +431,7 @@ describe('ValidatorShare', async function () { totalStaked: toWei('600'), shares: toWei('250'), reward: '0', - initialBalance: toWei('69500') + initialBalance: toWei('70305') }) }) }) @@ -475,7 +459,7 @@ describe('ValidatorShare', async function () { totalStaked: toWei('200'), shares: toWei('100'), reward: '0', - initialBalance: toWei('69900') + initialBalance: toWei('70705') }) }) @@ -489,7 +473,7 @@ describe('ValidatorShare', async function () { totalStaked: toWei('350'), shares: toWei('150'), reward: toWei('4500'), - initialBalance: toWei('69750') + initialBalance: toWei('70555') }) }) @@ -501,7 +485,7 @@ describe('ValidatorShare', async function () { totalStaked: toWei('600'), shares: toWei('250'), reward: '6428571428571428571428', - initialBalance: toWei('74000') + initialBalance: toWei('74805') }) }) }) @@ -521,7 +505,7 @@ describe('ValidatorShare', async function () { totalStaked: toWei('200'), shares: toWei('100'), reward: '0', - initialBalance: toWei('69900') + initialBalance: toWei('70705') }) }) @@ -537,7 +521,7 @@ describe('ValidatorShare', async function () { totalStaked: toWei('300'), shares: toWei('100'), reward: '0', - initialBalance: toWei('69900') + initialBalance: toWei('70750') }) }) @@ -553,7 +537,7 @@ describe('ValidatorShare', async function () { totalStaked: toWei('500'), shares: toWei('200'), reward: '0', - initialBalance: toWei('69700') + initialBalance: toWei('70505') }) }) @@ -569,7 +553,7 @@ describe('ValidatorShare', async function () { totalStaked: toWei('700'), shares: toWei('200'), reward: '0', - initialBalance: toWei('69700') + initialBalance: toWei('70550') }) }) }) @@ -596,7 +580,7 @@ describe('ValidatorShare', async function () { totalStaked: toWei('200'), shares: toWei('100'), reward: '0', - initialBalance: toWei('69900') + initialBalance: toWei('70705') }) }) @@ -613,7 +597,7 @@ describe('ValidatorShare', async function () { totalStaked: toWei('300'), shares: toWei('100'), reward: '0', - initialBalance: toWei('69900') + initialBalance: toWei('70750') }) }) @@ -630,7 +614,7 @@ describe('ValidatorShare', async function () { totalStaked: toWei('500'), shares: toWei('200'), reward: toWei('7500'), - initialBalance: toWei('69700') + initialBalance: toWei('70505') }) }) @@ -646,7 +630,7 @@ describe('ValidatorShare', async function () { totalStaked: toWei('700'), shares: toWei('200'), reward: toWei('4800'), - initialBalance: toWei('69700') + initialBalance: toWei('70550') }) }) }) @@ -964,7 +948,7 @@ describe('ValidatorShare', async function () { testSellVoucher({ returnedStake: aliceStake, reward: toWei('18000'), - initialBalance: new BN(0), + initialBalance: toWei('805'), validatorId: '8', user: Alice, userTotalStaked: toWei('0'), @@ -1033,7 +1017,7 @@ describe('ValidatorShare', async function () { testSellVoucher({ returnedStake: aliceStake, reward: toWei('18000'), - initialBalance: new BN(0), + initialBalance: toWei('805'), validatorId: '8', user: Alice, userTotalStaked: toWei('0'), @@ -1062,7 +1046,7 @@ describe('ValidatorShare', async function () { testSellVoucher({ returnedStake: aliceStake, reward: toWei('18000'), - initialBalance: new BN(0), + initialBalance: toWei('805'), validatorId: '8', user: Alice, userTotalStaked: toWei('0'), @@ -1084,7 +1068,7 @@ describe('ValidatorShare', async function () { testSellVoucher({ returnedStake: aliceStake, reward: toWei('18000'), - initialBalance: new BN(0), + initialBalance: toWei('805'), validatorId: '8', user: Alice, userTotalStaked: toWei('0'), @@ -1102,7 +1086,7 @@ describe('ValidatorShare', async function () { testSellVoucher({ returnedStake: aliceStake, reward: toWei('9000'), - initialBalance: new BN(0), + initialBalance: toWei('805'), validatorId: '8', user: Alice, userTotalStaked: toWei('0'), @@ -1115,7 +1099,7 @@ describe('ValidatorShare', async function () { testSellVoucher({ returnedStake: bobStake, reward: toWei('18000'), - initialBalance: new BN(0), + initialBalance: toWei('1200'), validatorId: '8', user: Bob, userTotalStaked: toWei('0'), @@ -1138,7 +1122,7 @@ describe('ValidatorShare', async function () { minClaimAmount: halfStake, returnedStake: halfStake, reward: toWei('18000'), - initialBalance: new BN(0), + initialBalance: toWei('805'), validatorId: '8', user: Alice, userTotalStaked: halfStake, @@ -1157,7 +1141,7 @@ describe('ValidatorShare', async function () { minClaimAmount: halfStake, returnedStake: halfStake, reward: '0', - initialBalance: new BN(toWei('18000')), + initialBalance: new BN(toWei('18805')), validatorId: '8', user: Alice, userTotalStaked: '0', @@ -1189,7 +1173,7 @@ describe('ValidatorShare', async function () { minClaimAmount: halfStake, returnedStake: halfStake, reward: toWei('18000'), - initialBalance: new BN(0), + initialBalance: toWei('805'), validatorId: '8', user: Alice, nonce: '1', @@ -1208,7 +1192,7 @@ describe('ValidatorShare', async function () { minClaimAmount: halfStake, returnedStake: halfStake, reward: '0', - initialBalance: new BN(toWei('18000')), + initialBalance: new BN(toWei('18805')), validatorId: '8', user: Alice, userTotalStaked: '0', @@ -1231,7 +1215,7 @@ describe('ValidatorShare', async function () { minClaimAmount: halfStake, returnedStake: halfStake, reward: toWei('18000'), - initialBalance: new BN(0), + initialBalance: toWei('805'), validatorId: '8', user: Alice, userTotalStaked: halfStake, @@ -1249,7 +1233,7 @@ describe('ValidatorShare', async function () { minClaimAmount: halfStake, returnedStake: halfStake, reward: '0', - initialBalance: new BN(toWei('18000')), + initialBalance: new BN(toWei('18805')), validatorId: '8', user: Alice, userTotalStaked: '0', @@ -1321,10 +1305,10 @@ describe('ValidatorShare', async function () { }) describe('withdrawRewards', function () { - const Alice = wallets[2].getChecksumAddressString() - const Bob = wallets[3].getChecksumAddressString() - const Eve = wallets[4].getChecksumAddressString() - const Carol = wallets[5].getChecksumAddressString() + const Alice = wallets[5].getChecksumAddressString() + const Bob = wallets[6].getChecksumAddressString() + const Eve = wallets[7].getChecksumAddressString() + const Carol = wallets[8].getChecksumAddressString() let totalDelegatorRewardsReceived //let totalSlashed @@ -1443,7 +1427,7 @@ describe('ValidatorShare', async function () { ) await stakeManagerValidator.withdrawRewards(this.validatorId) - const tokensLeft = await this.stakeToken.balanceOf(this.stakeManager.address) + const tokensLeft = await this.polToken.balanceOf(this.stakeManager.address) assertBigNumberEquality( this.initialStakeTokenBalance @@ -1464,7 +1448,7 @@ describe('ValidatorShare', async function () { totalStaked = new BN(0) //totalSlashed = new BN(0) totalDelegatorRewardsReceived = new BN(0) - this.initialStakeTokenBalance = await this.stakeToken.balanceOf(this.stakeManager.address) + this.initialStakeTokenBalance = await this.polToken.balanceOf(this.stakeManager.address) }) for (const step of timeline) { @@ -2146,7 +2130,7 @@ function shouldBuyShares({ shares, voucherValueExpected, totalStaked }) { }) } -function shouldWithdrawReward({ initialBalance, validatorId, user, reward, checkBalance = true }) { +function shouldWithdrawReward({ initialBalance, validatorId, user, reward, checkBalance = true, pol = false }) { if (reward > 0) { it('must emit Transfer', async function () { assertInTransaction(this.receipt, TestToken, 'Transfer', { @@ -2166,10 +2150,17 @@ function shouldWithdrawReward({ initialBalance, validatorId, user, reward, check } if (checkBalance) { - it('must have updated balance', async function () { - const balance = await this.stakeToken.balanceOf(user || this.user) - assertBigNumberEquality(balance, new BN(initialBalance).add(new BN(reward))) - }) + if (pol) { + it('must have updated balance', async function () { + const balance = await this.polToken.balanceOf(user || this.user) + assertBigNumberEquality(balance, new BN(initialBalance).add(new BN(reward))) + }) + } else { + it('must have updated balance', async function () { + const balance = await this.stakeToken.balanceOf(user || this.user) + assertBigNumberEquality(balance, new BN(initialBalance).add(new BN(reward))) + }) + } } it('must have liquid rewards == 0', async function () { diff --git a/test/units/staking/ValidatorShareHelper.js b/test/units/staking/ValidatorShareHelper.js index d6e7cb66..7f86a55e 100644 --- a/test/units/staking/ValidatorShareHelper.js +++ b/test/units/staking/ValidatorShareHelper.js @@ -55,12 +55,12 @@ export async function sellVoucherNew(validatorContract, delegator, minClaimAmoun return validatorContract_Delegator.sellVoucher_new(minClaimAmount.toString(), maxShares) } -export async function buyVoucherLegacy(validatorContract, amount, delegator, minSharesToMint) { +export async function buyVoucherPOL(validatorContract, amount, delegator, minSharesToMint) { const validatorContract_Delegator = validatorContract.connect(validatorContract.provider.getSigner(delegator)) - return validatorContract_Delegator.buyVoucherLegacy(amount.toString(), minSharesToMint || 0) + return validatorContract_Delegator.buyVoucherPOL(amount.toString(), minSharesToMint || 0) } -export async function sellVoucherLegacy(validatorContract, delegator, minClaimAmount, maxShares) { +export async function sellVoucherPOL(validatorContract, delegator, minClaimAmount, maxShares) { if (maxShares === undefined) { maxShares = await validatorContract.balanceOf(delegator) } @@ -71,10 +71,10 @@ export async function sellVoucherLegacy(validatorContract, delegator, minClaimAm const validatorContract_Delegator = validatorContract.connect(validatorContract.provider.getSigner(delegator)) - return validatorContract_Delegator.sellVoucherLegacy(minClaimAmount, maxShares) + return validatorContract_Delegator.sellVoucherPOL(minClaimAmount, maxShares) } -export async function sellVoucherNewLegacy(validatorContract, delegator, minClaimAmount, maxShares) { +export async function sellVoucherNewPOL(validatorContract, delegator, minClaimAmount, maxShares) { if (maxShares === undefined) { maxShares = await validatorContract.balanceOf(delegator) } @@ -84,5 +84,5 @@ export async function sellVoucherNewLegacy(validatorContract, delegator, minClai } const validatorContract_Delegator = validatorContract.connect(validatorContract.provider.getSigner(delegator)) - return validatorContract_Delegator.sellVoucher_newLegacy(minClaimAmount.toString(), maxShares) + return validatorContract_Delegator.sellVoucher_newPOL(minClaimAmount.toString(), maxShares) } diff --git a/test/units/staking/ValidatorShareLegacy.test.js b/test/units/staking/ValidatorSharePol.test.js similarity index 84% rename from test/units/staking/ValidatorShareLegacy.test.js rename to test/units/staking/ValidatorSharePol.test.js index 95757993..8079aff4 100644 --- a/test/units/staking/ValidatorShareLegacy.test.js +++ b/test/units/staking/ValidatorSharePol.test.js @@ -7,9 +7,9 @@ import { EventsHub } from '../../helpers/artifacts.js' import testHelpers from '@openzeppelin/test-helpers' -import { checkPoint, assertBigNumberEquality, updateSlashedAmounts, assertInTransaction } from '../../helpers/utils.js' +import { checkPoint, assertBigNumberEquality, assertInTransaction } from '../../helpers/utils.js' import { wallets, freshDeploy, approveAndStake } from './deployment.js' -import { buyVoucherLegacy, sellVoucherLegacy, sellVoucherNewLegacy } from './ValidatorShareHelper.js' +import { buyVoucherPOL, sellVoucherPOL, sellVoucherNewPOL } from './ValidatorShareHelper.js' const BN = testHelpers.BN const expectRevert = testHelpers.expectRevert const toWei = web3.utils.toWei @@ -18,30 +18,30 @@ const ExchangeRatePrecision = new BN('100000000000000000000000000000') const Dynasty = 8 const ValidatorDefaultStake = new BN(toWei('100')) -describe('ValidatorShareLegacy', function () { +describe('ValidatorSharePOL', function () { const wei100 = toWei('100') async function doDeploy() { await freshDeploy.call(this) - this.stakeToken = await ERC20Permit.deploy('POL', 'POL', '1.1.0') - this.legacyToken = await TestToken.deploy('MATIC', 'MATIC') + this.polToken = await ERC20Permit.deploy('POL', 'POL', '1.1.0') + this.stakeToken = await TestToken.deploy('MATIC', 'MATIC') - this.migration = await PolygonMigration.deploy(this.legacyToken.address, this.stakeToken.address) + this.migration = await PolygonMigration.deploy(this.stakeToken.address, this.polToken.address) await this.stakeToken.mint(this.migration.address, toWei('30000000')) - await this.legacyToken.mint(this.migration.address, toWei('40000000')) + await this.polToken.mint(this.migration.address, toWei('40000000')) await this.governance.update( this.stakeManager.address, - this.stakeManager.interface.encodeFunctionData('setStakingToken', [this.legacyToken.address]) + this.stakeManager.interface.encodeFunctionData('setStakingToken', [this.stakeToken.address]) ) - await this.legacyToken.mint(this.stakeManager.address, toWei('10000000')) + await this.stakeToken.mint(this.stakeManager.address, toWei('10000000')) await this.governance.update( this.stakeManager.address, - this.stakeManager.interface.encodeFunctionData('initializeLegacy', [this.stakeToken.address, this.migration.address]) + this.stakeManager.interface.encodeFunctionData('initializePOL', [this.polToken.address, this.migration.address]) ) this.validatorId = '8' @@ -63,19 +63,19 @@ describe('ValidatorShareLegacy', function () { wallet: this.validatorUser, stakeAmount: this.stakeAmount, acceptDelegation: true, - legacy: true + pol: true }) await this.governance.update( this.stakeManager.address, - this.stakeManager.interface.encodeFunctionData('forceUnstakeLegacy', [i + 1]) + this.stakeManager.interface.encodeFunctionData('forceUnstakePOL', [i + 1]) ) await this.stakeManager.forceFinalizeCommit() await this.stakeManager.advanceEpoch(Dynasty) const stakeManagerValidator = this.stakeManager.connect( this.stakeManager.provider.getSigner(this.validatorUser.getChecksumAddressString()) ) - await stakeManagerValidator.unstakeClaimLegacy(i + 1) + await stakeManagerValidator.unstakeClaimPOL(i + 1) await this.stakeManager.resetSignerUsed(this.validatorUser.getChecksumAddressString()) } @@ -83,7 +83,7 @@ describe('ValidatorShareLegacy', function () { wallet: this.validatorUser, stakeAmount: this.stakeAmount, acceptDelegation: true, - legacy: true + pol: true }) await this.stakeManager.forceFinalizeCommit() @@ -101,20 +101,18 @@ describe('ValidatorShareLegacy', function () { const mintAmount = new BN(toWei('70000')).toString() - await this.legacyToken.mint(this.alice, mintAmount) + await this.polToken.mint(this.alice, mintAmount) + const polTokenAlice = this.polToken.connect(this.polToken.provider.getSigner(this.alice)) + await polTokenAlice.approve(this.stakeManager.address, mintAmount) - const legacyTokenAlice = this.legacyToken.connect(this.legacyToken.provider.getSigner(this.alice)) - await legacyTokenAlice.approve(this.stakeManager.address, mintAmount) - - await this.legacyToken.mint(this.bob, mintAmount) - - const legacyTokenBob = this.legacyToken.connect(this.legacyToken.provider.getSigner(this.bob)) - await legacyTokenBob.approve(this.stakeManager.address, mintAmount) + await this.polToken.mint(this.bob, mintAmount) + const polTokenBob = this.polToken.connect(this.polToken.provider.getSigner(this.bob)) + await polTokenBob.approve(this.stakeManager.address, mintAmount) }) } describe('buyVoucher', function () { - function testbuyVoucherLegacy({ + function testbuyVoucherPOL({ voucherValue, voucherValueExpected, userTotalStaked, @@ -124,7 +122,7 @@ describe('ValidatorShareLegacy', function () { initialBalance }) { it('must buy voucher', async function () { - this.receipt = await (await buyVoucherLegacy(this.validatorContract, voucherValue, this.user, shares)).wait() + this.receipt = await (await buyVoucherPOL(this.validatorContract, voucherValue, this.user, shares)).wait() }) shouldBuyShares({ @@ -152,7 +150,7 @@ describe('ValidatorShareLegacy', function () { this.user = this.alice }) - testbuyVoucherLegacy({ + testbuyVoucherPOL({ voucherValue: toWei('100'), voucherValueExpected: toWei('100'), userTotalStaked: toWei('100'), @@ -170,7 +168,7 @@ describe('ValidatorShareLegacy', function () { this.user = this.alice }) - testbuyVoucherLegacy({ + testbuyVoucherPOL({ voucherValue: toWei('100'), voucherValueExpected: toWei('100'), userTotalStaked: toWei('100'), @@ -192,7 +190,7 @@ describe('ValidatorShareLegacy', function () { }) it('reverts', async function () { - await expectRevert(buyVoucherLegacy(this.validatorContract, toWei('150'), this.alice), 'Delegation is disabled') + await expectRevert(buyVoucherPOL(this.validatorContract, toWei('150'), this.alice), 'Delegation is disabled') }) }) @@ -208,7 +206,7 @@ describe('ValidatorShareLegacy', function () { it('reverts', async function () { await expectRevert( - buyVoucherLegacy(this.validatorContract, web3.utils.toWei('150'), this.alice), + buyVoucherPOL(this.validatorContract, web3.utils.toWei('150'), this.alice), 'Delegation is disabled' ) }) @@ -222,7 +220,7 @@ describe('ValidatorShareLegacy', function () { }) describe('1st purchase', async function () { - testbuyVoucherLegacy({ + testbuyVoucherPOL({ voucherValue: toWei('100'), voucherValueExpected: toWei('100'), userTotalStaked: toWei('100'), @@ -234,7 +232,7 @@ describe('ValidatorShareLegacy', function () { }) describe('2nd purchase', async function () { - testbuyVoucherLegacy({ + testbuyVoucherPOL({ voucherValue: toWei('150'), voucherValueExpected: toWei('150'), userTotalStaked: toWei('250'), @@ -246,7 +244,7 @@ describe('ValidatorShareLegacy', function () { }) describe('3rd purchase', async function () { - testbuyVoucherLegacy({ + testbuyVoucherPOL({ voucherValue: toWei('250'), voucherValueExpected: toWei('250'), userTotalStaked: toWei('500'), @@ -274,7 +272,7 @@ describe('ValidatorShareLegacy', function () { describe('1st purchase', async function () { advanceCheckpointAfter() - testbuyVoucherLegacy({ + testbuyVoucherPOL({ voucherValue: toWei('100'), voucherValueExpected: toWei('100'), userTotalStaked: toWei('100'), @@ -288,7 +286,7 @@ describe('ValidatorShareLegacy', function () { describe('2nd purchase', async function () { advanceCheckpointAfter() - testbuyVoucherLegacy({ + testbuyVoucherPOL({ voucherValue: toWei('150'), voucherValueExpected: toWei('150'), userTotalStaked: toWei('250'), @@ -300,7 +298,7 @@ describe('ValidatorShareLegacy', function () { }) describe('3rd purchase', async function () { - testbuyVoucherLegacy({ + testbuyVoucherPOL({ voucherValue: toWei('250'), voucherValueExpected: toWei('250'), userTotalStaked: toWei('500'), @@ -320,7 +318,7 @@ describe('ValidatorShareLegacy', function () { this.user = this.alice }) - testbuyVoucherLegacy({ + testbuyVoucherPOL({ voucherValue: toWei('100'), voucherValueExpected: toWei('100'), userTotalStaked: toWei('100'), @@ -336,7 +334,7 @@ describe('ValidatorShareLegacy', function () { this.user = this.bob }) - testbuyVoucherLegacy({ + testbuyVoucherPOL({ voucherValue: toWei('100'), voucherValueExpected: toWei('100'), userTotalStaked: toWei('100'), @@ -352,7 +350,7 @@ describe('ValidatorShareLegacy', function () { this.user = this.alice }) - testbuyVoucherLegacy({ + testbuyVoucherPOL({ voucherValue: toWei('200'), voucherValueExpected: toWei('200'), userTotalStaked: toWei('300'), @@ -368,7 +366,7 @@ describe('ValidatorShareLegacy', function () { this.user = this.bob }) - testbuyVoucherLegacy({ + testbuyVoucherPOL({ voucherValue: toWei('200'), voucherValueExpected: toWei('200'), userTotalStaked: toWei('300'), @@ -395,7 +393,7 @@ describe('ValidatorShareLegacy', function () { this.user = this.alice }) - testbuyVoucherLegacy({ + testbuyVoucherPOL({ voucherValue: toWei('100'), voucherValueExpected: toWei('100'), userTotalStaked: toWei('100'), @@ -412,7 +410,7 @@ describe('ValidatorShareLegacy', function () { this.user = this.bob }) - testbuyVoucherLegacy({ + testbuyVoucherPOL({ voucherValue: toWei('100'), voucherValueExpected: toWei('100'), userTotalStaked: toWei('100'), @@ -429,7 +427,7 @@ describe('ValidatorShareLegacy', function () { this.user = this.alice }) - testbuyVoucherLegacy({ + testbuyVoucherPOL({ voucherValue: toWei('200'), voucherValueExpected: toWei('200'), userTotalStaked: toWei('300'), @@ -445,7 +443,7 @@ describe('ValidatorShareLegacy', function () { this.user = this.bob }) - testbuyVoucherLegacy({ + testbuyVoucherPOL({ voucherValue: toWei('200'), voucherValueExpected: toWei('200'), userTotalStaked: toWei('300'), @@ -465,7 +463,7 @@ describe('ValidatorShareLegacy', function () { }) it('reverts', async function () { - await expectRevert(buyVoucherLegacy(this.validatorContract, toWei('100'), this.alice, toWei('100')), 'locked') + await expectRevert(buyVoucherPOL(this.validatorContract, toWei('100'), this.alice, toWei('100')), 'locked') }) }) @@ -480,7 +478,7 @@ describe('ValidatorShareLegacy', function () { }) it('reverts', async function () { - await expectRevert(buyVoucherLegacy(this.validatorContract, new BN(toWei('100')), this.alice), 'locked') + await expectRevert(buyVoucherPOL(this.validatorContract, new BN(toWei('100')), this.alice), 'locked') }) }) }) @@ -494,16 +492,16 @@ describe('ValidatorShareLegacy', function () { this.totalStaked = new BN(0) const voucherAmount = new BN(toWei('70000')).toString() - await this.legacyToken.mint(this.user, voucherAmount) - const legacyTokenUser = this.legacyToken.connect(this.legacyToken.provider.getSigner(this.user)) - await legacyTokenUser.approve(this.stakeManager.address, voucherAmount) + await this.polToken.mint(this.user, voucherAmount) + const polTokenUser = this.polToken.connect(this.polToken.provider.getSigner(this.user)) + await polTokenUser.approve(this.stakeManager.address, voucherAmount) }) it('must buy voucher', async function () { const voucherValue = toWei('100') this.totalStaked = this.totalStaked.add(new BN(voucherValue)) - await buyVoucherLegacy(this.validatorContract, voucherValue, this.user) + await buyVoucherPOL(this.validatorContract, voucherValue, this.user) }) it('exchange rate must be correct', async function () { @@ -515,7 +513,7 @@ describe('ValidatorShareLegacy', function () { const voucherValue = toWei('5000') this.totalStaked = this.totalStaked.add(new BN(voucherValue)) - await buyVoucherLegacy(this.validatorContract, voucherValue, this.user) + await buyVoucherPOL(this.validatorContract, voucherValue, this.user) }) it('exchange rate must be correct', async function () { @@ -527,19 +525,19 @@ describe('ValidatorShareLegacy', function () { before(doDeploy) before(async function () { this.user = wallets[2].getAddressString() - await this.legacyToken.mint(this.user, toWei('250')) + await this.polToken.mint(this.user, toWei('250')) this.beforeExchangeRate = await this.validatorContract.exchangeRate() - const legacyTokenUser = this.legacyToken.connect(this.legacyToken.provider.getSigner(this.user)) - await legacyTokenUser.approve(this.stakeManager.address, toWei('250')) + const polTokenUser = this.polToken.connect(this.polToken.provider.getSigner(this.user)) + await polTokenUser.approve(this.stakeManager.address, toWei('250')) }) it('must purchase voucher', async function () { - await buyVoucherLegacy(this.validatorContract, toWei('100'), this.user) + await buyVoucherPOL(this.validatorContract, toWei('100'), this.user) }) it('must sell voucher', async function () { - await sellVoucherLegacy(this.validatorContract, this.user) + await sellVoucherPOL(this.validatorContract, this.user) }) it('must have initial exchange rate', async function () { @@ -559,10 +557,10 @@ describe('ValidatorShareLegacy', function () { await doDeploy.call(this) const stake = async ({ user, stake }) => { - await this.legacyToken.mint(user, stake) - const legacyTokenUser = this.legacyToken.connect(this.legacyToken.provider.getSigner(user)) - await legacyTokenUser.approve(this.stakeManager.address, stake) - await buyVoucherLegacy(this.validatorContract, stake, user) + await this.polToken.mint(user, stake) + const polTokenUser = this.polToken.connect(this.polToken.provider.getSigner(user)) + await polTokenUser.approve(this.stakeManager.address, stake) + await buyVoucherPOL(this.validatorContract, stake, user) } await stake({ user: Alice, stake: aliceStake.toString() }) @@ -576,7 +574,7 @@ describe('ValidatorShareLegacy', function () { } } - function testSellVoucherLegacyNew({ + function testsellVoucherPOLNew({ returnedStake, reward, initialBalance, @@ -591,11 +589,11 @@ describe('ValidatorShareLegacy', function () { }) { if (minClaimAmount) { it('must sell voucher with slippage', async function () { - this.receipt = await (await sellVoucherNewLegacy(this.validatorContract, user, minClaimAmount)).wait() + this.receipt = await (await sellVoucherNewPOL(this.validatorContract, user, minClaimAmount)).wait() }) } else { it('must sell voucher', async function () { - this.receipt = await (await sellVoucherNewLegacy(this.validatorContract, user)).wait() + this.receipt = await (await sellVoucherNewPOL(this.validatorContract, user)).wait() }) } @@ -634,7 +632,7 @@ describe('ValidatorShareLegacy', function () { }) } - function testSellVoucherLegacy({ + function testsellVoucherPOL({ returnedStake, reward, initialBalance, @@ -648,11 +646,11 @@ describe('ValidatorShareLegacy', function () { }) { if (minClaimAmount) { it('must sell voucher with slippage', async function () { - this.receipt = await (await sellVoucherLegacy(this.validatorContract, user, minClaimAmount.toString())).wait() + this.receipt = await (await sellVoucherPOL(this.validatorContract, user, minClaimAmount.toString())).wait() }) } else { it('must sell voucher', async function () { - this.receipt = await (await sellVoucherLegacy(this.validatorContract, user)).wait() + this.receipt = await (await sellVoucherPOL(this.validatorContract, user)).wait() }) } @@ -682,7 +680,7 @@ describe('ValidatorShareLegacy', function () { describe('when Alice sells voucher', function () { before(doDeployAndBuyVoucherForAliceAndBob) - testSellVoucherLegacy({ + testsellVoucherPOL({ returnedStake: aliceStake, reward: toWei('18000'), initialBalance: new BN(0), @@ -703,7 +701,7 @@ describe('ValidatorShareLegacy', function () { ) }) - testSellVoucherLegacy({ + testsellVoucherPOL({ returnedStake: aliceStake, reward: toWei('18000'), initialBalance: new BN(0), @@ -721,7 +719,7 @@ describe('ValidatorShareLegacy', function () { it('reverts', async function () { const maxShares = await this.validatorContract.balanceOf(Alice) const validatorAlice = this.validatorContract.connect(this.validatorContract.provider.getSigner(Alice)) - await expectRevert(validatorAlice.sellVoucherLegacy(toWei('100.00001'), maxShares), 'Too much requested') + await expectRevert(validatorAlice.sellVoucherPOL(toWei('100.00001'), maxShares), 'Too much requested') }) }) @@ -732,7 +730,7 @@ describe('ValidatorShareLegacy', function () { await this.stakeManager.testLockShareContract(this.validatorId, true) }) - testSellVoucherLegacy({ + testsellVoucherPOL({ returnedStake: aliceStake, reward: toWei('18000'), initialBalance: new BN(0), @@ -754,7 +752,7 @@ describe('ValidatorShareLegacy', function () { await this.stakeManager.advanceEpoch(Dynasty) }) - testSellVoucherLegacy({ + testsellVoucherPOL({ returnedStake: aliceStake, reward: toWei('18000'), initialBalance: new BN(0), @@ -772,7 +770,7 @@ describe('ValidatorShareLegacy', function () { }) describe('when Alice sells', function () { - testSellVoucherLegacy({ + testsellVoucherPOL({ returnedStake: aliceStake, reward: toWei('9000'), initialBalance: new BN(0), @@ -785,7 +783,7 @@ describe('ValidatorShareLegacy', function () { }) describe('when Bob sells', function () { - testSellVoucherLegacy({ + testsellVoucherPOL({ returnedStake: bobStake, reward: toWei('18000'), initialBalance: new BN(0), @@ -806,7 +804,7 @@ describe('ValidatorShareLegacy', function () { const halfStake = aliceStake.div(new BN('2')) describe('when Alice sells 50%', function () { - testSellVoucherLegacyNew({ + testsellVoucherPOLNew({ shares: new BN(toWei('50')), minClaimAmount: halfStake, returnedStake: halfStake, @@ -825,7 +823,7 @@ describe('ValidatorShareLegacy', function () { await this.stakeManager.advanceEpoch(1) }) - testSellVoucherLegacyNew({ + testsellVoucherPOLNew({ shares: new BN(toWei('50')), minClaimAmount: halfStake, returnedStake: halfStake, @@ -848,7 +846,7 @@ describe('ValidatorShareLegacy', function () { const halfStake = aliceStake.div(new BN('2')) describe('when Alice sells 50%', function () { - testSellVoucherLegacy({ + testsellVoucherPOL({ shares: new BN(toWei('50')).toString(), minClaimAmount: halfStake, returnedStake: halfStake, @@ -866,7 +864,7 @@ describe('ValidatorShareLegacy', function () { await this.stakeManager.advanceEpoch(1) }) - testSellVoucherLegacy({ + testsellVoucherPOL({ shares: new BN(toWei('50')), minClaimAmount: halfStake, returnedStake: halfStake, @@ -904,12 +902,12 @@ describe('ValidatorShareLegacy', function () { if (expectedReward.toString() === '0') { it('reverts', async function () { const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(user)) - await expectRevert(validatorUser.withdrawRewardsLegacy(), 'Too small rewards amount') + await expectRevert(validatorUser.withdrawRewardsPOL(), 'Too small rewards amount') }) } else { it('must withdraw rewards', async function () { const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(user)) - this.receipt = await (await validatorUser.withdrawRewardsLegacy()).wait() + this.receipt = await (await validatorUser.withdrawRewardsPOL()).wait() }) shouldWithdrawReward({ @@ -928,10 +926,10 @@ describe('ValidatorShareLegacy', function () { totalInitialBalance = totalInitialBalance.add(initialBalance) totalStaked = totalStaked.add(new BN(amount)) - await this.legacyToken.mint(user, initialBalance.add(amount).toString()) - const legacyTokenUser = this.legacyToken.connect(this.legacyToken.provider.getSigner(user)) - await legacyTokenUser.approve(this.stakeManager.address, amount.toString()) - await buyVoucherLegacy(this.validatorContract, amount.toString(), user) + await this.polToken.mint(user, initialBalance.add(amount).toString()) + const polTokenUser = this.polToken.connect(this.polToken.provider.getSigner(user)) + await polTokenUser.approve(this.stakeManager.address, amount.toString()) + await buyVoucherPOL(this.validatorContract, amount.toString(), user) delegators[user] = delegators[user] || { rewards: new BN(0) } @@ -993,12 +991,12 @@ describe('ValidatorShareLegacy', function () { const stakeManagerValidator = this.stakeManager.connect( this.stakeManager.provider.getSigner(this.validatorUser.getChecksumAddressString()) ) - await stakeManagerValidator.withdrawRewardsLegacy(this.validatorId) + await stakeManagerValidator.withdrawRewardsPOL(this.validatorId) - const tokensLeft = await this.stakeToken.balanceOf(this.stakeManager.address) + const tokensLeft = await this.polToken.balanceOf(this.stakeManager.address) assertBigNumberEquality( - this.initialStakeTokenBalance + this.initialPolTokenBalance .add(totalStaked.toString()) .sub(totalReceived), tokensLeft @@ -1014,7 +1012,7 @@ describe('ValidatorShareLegacy', function () { totalInitialBalance = new BN(0) totalStaked = new BN(0) totalDelegatorRewardsReceived = new BN(0) - this.initialStakeTokenBalance = await this.stakeToken.balanceOf(this.stakeManager.address) + this.initialPolTokenBalance = await this.polToken.balanceOf(this.stakeManager.address) }) for (const step of timeline) { @@ -1079,7 +1077,7 @@ describe('ValidatorShareLegacy', function () { it('reverts', async function () { const validatorContractAlice = this.validatorContract.connect(this.validatorContract.provider.getSigner(Alice)) - await expectRevert(validatorContractAlice.withdrawRewardsLegacy(), 'Too small rewards amount') + await expectRevert(validatorContractAlice.withdrawRewardsPOL(), 'Too small rewards amount') }) }) @@ -1097,17 +1095,17 @@ describe('ValidatorShareLegacy', function () { before(async function () { const amount = toWei('100') - await this.legacyToken.mint(Alice, amount) - const legacyTokenAlice = this.legacyToken.connect(this.legacyToken.provider.getSigner(Alice)) - await legacyTokenAlice.approve(this.stakeManager.address, amount) - await buyVoucherLegacy(this.validatorContract, amount, Alice) + await this.polToken.mint(Alice, amount) + const polTokenAlice = this.polToken.connect(this.polToken.provider.getSigner(Alice)) + await polTokenAlice.approve(this.stakeManager.address, amount) + await buyVoucherPOL(this.validatorContract, amount, Alice) await checkPoint([this.validatorUser], this.rootChainOwner, this.stakeManager) await this.stakeManager.testLockShareContract(this.validatorId, true) }) it('must withdraw rewards', async function () { const validatorContractAlice = this.validatorContract.connect(this.validatorContract.provider.getSigner(Alice)) - this.receipt = await (await validatorContractAlice.withdrawRewardsLegacy()).wait() + this.receipt = await (await validatorContractAlice.withdrawRewardsPOL()).wait() }) shouldWithdrawReward({ @@ -1122,10 +1120,10 @@ describe('ValidatorShareLegacy', function () { before(doDeploy) before(async function () { const amount = toWei('100') - await this.legacyToken.mint(Alice, amount) - const legacyTokenAlice = this.legacyToken.connect(this.legacyToken.provider.getSigner(Alice)) - await legacyTokenAlice.approve(this.stakeManager.address, amount) - await buyVoucherLegacy(this.validatorContract, amount, Alice) + await this.polToken.mint(Alice, amount) + const polTokenAlice = this.polToken.connect(this.polToken.provider.getSigner(Alice)) + await polTokenAlice.approve(this.stakeManager.address, amount) + await buyVoucherPOL(this.validatorContract, amount, Alice) await checkPoint([this.validatorUser], this.rootChainOwner, this.stakeManager) const stakeManagerAlice = this.stakeManager.connect( this.stakeManager.provider.getSigner(this.validatorUser.getChecksumAddressString()) @@ -1136,7 +1134,7 @@ describe('ValidatorShareLegacy', function () { it('must withdraw rewards', async function () { const validatorContractAlice = this.validatorContract.connect(this.validatorContract.provider.getSigner(Alice)) - this.receipt = await (await validatorContractAlice.withdrawRewardsLegacy()).wait() + this.receipt = await (await validatorContractAlice.withdrawRewardsPOL()).wait() }) shouldWithdrawReward({ @@ -1154,11 +1152,11 @@ describe('ValidatorShareLegacy', function () { before(async function () { this.user = wallets[2].getChecksumAddressString() - await this.legacyToken.mint(this.user, this.stakeAmount.toString()) - const legacyTokenUser = this.legacyToken.connect(this.legacyToken.provider.getSigner(this.user)) - await legacyTokenUser.approve(this.stakeManager.address, this.stakeAmount.toString()) + await this.polToken.mint(this.user, this.stakeAmount.toString()) + const polTokenUser = this.polToken.connect(this.polToken.provider.getSigner(this.user)) + await polTokenUser.approve(this.stakeManager.address, this.stakeAmount.toString()) - await buyVoucherLegacy(this.validatorContract, this.stakeAmount.toString(), this.user) + await buyVoucherPOL(this.validatorContract, this.stakeAmount.toString(), this.user) this.shares = await this.validatorContract.balanceOf(this.user) if (!skipCheckpoint) { @@ -1179,7 +1177,7 @@ describe('ValidatorShareLegacy', function () { it('must restake', async function () { const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.user)) - this.receipt = await (await validatorUser.restakeLegacy()).wait() + this.receipt = await (await validatorUser.restakePOL()).wait() }) shouldBuyShares({ @@ -1211,7 +1209,7 @@ describe('ValidatorShareLegacy', function () { it('reverts', async function () { const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.user)) - await expectRevert(validatorUser.restakeLegacy(), 'Too small rewards to restake') + await expectRevert(validatorUser.restakePOL(), 'Too small rewards to restake') }) }) @@ -1227,7 +1225,7 @@ describe('ValidatorShareLegacy', function () { it('reverts', async function () { const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.user)) - await expectRevert(validatorUser.restakeLegacy(), 'Delegation is disabled') + await expectRevert(validatorUser.restakePOL(), 'Delegation is disabled') }) }) @@ -1242,7 +1240,7 @@ describe('ValidatorShareLegacy', function () { it('reverts', async function () { const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.user)) - await expectRevert(validatorUser.restakeLegacy(), 'locked') + await expectRevert(validatorUser.restakePOL(), 'locked') }) }) @@ -1255,7 +1253,7 @@ describe('ValidatorShareLegacy', function () { it('reverts', async function () { const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.user)) - await expectRevert(validatorUser.restakeLegacy(), 'locked') + await expectRevert(validatorUser.restakePOL(), 'locked') }) }) }) @@ -1266,22 +1264,22 @@ describe('ValidatorShareLegacy', function () { before(async function () { this.user = wallets[2].getChecksumAddressString() - await this.legacyToken.mint(this.user, this.stakeAmount.toString()) - const legacyTokenUser = this.legacyToken.connect(this.legacyToken.provider.getSigner(this.user)) - await legacyTokenUser.approve(this.stakeManager.address, this.stakeAmount.toString()) + await this.polToken.mint(this.user, this.stakeAmount.toString()) + const polTokenUser = this.polToken.connect(this.polToken.provider.getSigner(this.user)) + await polTokenUser.approve(this.stakeManager.address, this.stakeAmount.toString()) this.totalStaked = this.stakeAmount }) if (!skipBuy) { before('buy', async function () { - await buyVoucherLegacy(this.validatorContract, this.stakeAmount.toString(), this.user) + await buyVoucherPOL(this.validatorContract, this.stakeAmount.toString(), this.user) }) } if (!skipSell) { before('sell', async function () { - await sellVoucherLegacy(this.validatorContract, this.user) + await sellVoucherPOL(this.validatorContract, this.user) }) } } @@ -1300,7 +1298,7 @@ describe('ValidatorShareLegacy', function () { it('must unstake', async function () { const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.user)) - this.receipt = await (await validatorUser.unstakeClaimTokensLegacy()).wait() + this.receipt = await (await validatorUser.unstakeClaimTokensPOL()).wait() }) it('must emit DelegatorUnstaked', async function () { @@ -1323,7 +1321,7 @@ describe('ValidatorShareLegacy', function () { it('reverts', async function () { const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.user)) await expectRevert( - validatorUser.unstakeClaimTokensLegacy(), + validatorUser.unstakeClaimTokensPOL(), 'Incomplete withdrawal period' ) }) @@ -1335,7 +1333,7 @@ describe('ValidatorShareLegacy', function () { it('reverts', async function () { const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.user)) await expectRevert( - validatorUser.unstakeClaimTokensLegacy(), + validatorUser.unstakeClaimTokensPOL(), 'Incomplete withdrawal period' ) }) @@ -1347,7 +1345,7 @@ describe('ValidatorShareLegacy', function () { it('reverts', async function () { const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.user)) await expectRevert( - validatorUser.unstakeClaimTokensLegacy(), + validatorUser.unstakeClaimTokensPOL(), 'Incomplete withdrawal period' ) }) @@ -1360,9 +1358,9 @@ describe('ValidatorShareLegacy', function () { before('sell shares twice', async function () { this.claimAmount = this.stakeAmount.div(new BN('2')) - await sellVoucherNewLegacy(this.validatorContract, this.user, this.claimAmount) + await sellVoucherNewPOL(this.validatorContract, this.user, this.claimAmount) await checkPoint([this.validatorUser], this.rootChainOwner, this.stakeManager) - await sellVoucherNewLegacy(this.validatorContract, this.user, this.claimAmount) + await sellVoucherNewPOL(this.validatorContract, this.user, this.claimAmount) }) before('checkpoint', async function () { @@ -1376,7 +1374,7 @@ describe('ValidatorShareLegacy', function () { it('must claim 1st unstake', async function () { const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.user)) - this.receipt = await (await validatorUser.unstakeClaimTokens_newLegacy('1')).wait() + this.receipt = await (await validatorUser.unstakeClaimTokens_newPOL('1')).wait() }) it('must emit DelegatorUnstakeWithId', async function () { @@ -1390,7 +1388,7 @@ describe('ValidatorShareLegacy', function () { it('must claim 2nd unstake', async function () { const validatorUser = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.user)) - this.receipt = await (await validatorUser.unstakeClaimTokens_newLegacy('2')).wait() + this.receipt = await (await validatorUser.unstakeClaimTokens_newPOL('2')).wait() }) it('must emit DelegatorUnstakeWithId', async function () { @@ -1413,11 +1411,11 @@ describe('ValidatorShareLegacy', function () { describe('when Alice and Bob buy vouchers (1 checkpoint in-between) and Alice withdraw the rewards', function () { deployAliceAndBob() before(async function () { - await buyVoucherLegacy(this.validatorContract, toWei('100'), this.alice) + await buyVoucherPOL(this.validatorContract, toWei('100'), this.alice) await checkPoint([this.validatorUser], this.rootChainOwner, this.stakeManager) - await buyVoucherLegacy(this.validatorContract, toWei('4600'), this.bob) + await buyVoucherPOL(this.validatorContract, toWei('4600'), this.bob) const validatorAlice = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.alice)) - await validatorAlice.withdrawRewardsLegacy() + await validatorAlice.withdrawRewardsPOL() }) it('Bob must call getLiquidRewards', async function () { @@ -1433,13 +1431,13 @@ describe('ValidatorShareLegacy', function () { let initialSharesBalance before('Alice purchases voucher', async function () { - await buyVoucherLegacy(this.validatorContract, toWei('100'), this.alice) + await buyVoucherPOL(this.validatorContract, toWei('100'), this.alice) initialSharesBalance = await this.validatorContract.balanceOf(this.alice) }) it('must Transfer shares', async function () { const validatorAlice = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.alice)) - await validatorAlice.transfer(this.bob, initialSharesBalance) + await validatorAlice.transferPOL(this.bob, initialSharesBalance) }) it('Alice must have 0 shares', async function () { @@ -1457,25 +1455,31 @@ describe('ValidatorShareLegacy', function () { let initialAliceSharesBalance let initialBobSharesBalance - let initialAliceMaticBalance - let initialBobMaticBalance + let initialAlicePolBalance + let initialBobPolBalance + + let initialAliceStakeBalance + let initialBobStakeBalance before('Alice and Bob purchases voucher, checkpoint is commited', async function () { - await buyVoucherLegacy(this.validatorContract, ValidatorDefaultStake, this.alice) - await buyVoucherLegacy(this.validatorContract, ValidatorDefaultStake, this.bob) + await buyVoucherPOL(this.validatorContract, ValidatorDefaultStake, this.alice) + await buyVoucherPOL(this.validatorContract, ValidatorDefaultStake, this.bob) initialAliceSharesBalance = await this.validatorContract.balanceOf(this.alice) initialBobSharesBalance = await this.validatorContract.balanceOf(this.bob) - initialAliceMaticBalance = await this.legacyToken.balanceOf(this.alice) - initialBobMaticBalance = await this.legacyToken.balanceOf(this.bob) + initialAlicePolBalance = await this.polToken.balanceOf(this.alice) + initialBobPolBalance = await this.polToken.balanceOf(this.bob) + + initialAliceStakeBalance = await this.stakeToken.balanceOf(this.alice) + initialBobStakeBalance = await this.stakeToken.balanceOf(this.bob) await checkPoint([this.validatorUser], this.rootChainOwner, this.stakeManager) }) it('must Transfer shares', async function () { const validatorAlice = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.alice)) - this.receipt = await (await validatorAlice.transfer(this.bob, initialAliceSharesBalance)).wait() + this.receipt = await (await validatorAlice.transferPOL(this.bob, initialAliceSharesBalance)).wait() }) it('must emit DelegatorClaimedRewards for Alice', async function () { @@ -1486,17 +1490,18 @@ describe('ValidatorShareLegacy', function () { }) }) - it('Alice must claim 3000 stake', async function () { + it('Alice must claim 3000 pol', async function () { assertBigNumberEquality( - await this.stakeToken.balanceOf(this.alice), - toWei('3000') + await this.polToken.balanceOf(this.alice), + initialAlicePolBalance.add(toWei('3000')) ) }) - it('Alice must have unchanged legacy', async function () { + it('Alice must have unchanged matic', async function () { assertBigNumberEquality( - await this.legacyToken.balanceOf(this.alice), - initialAliceMaticBalance) + await this.stakeToken.balanceOf(this.alice), + initialAliceStakeBalance + ) }) it('Alice must have 0 liquid rewards', async function () { @@ -1522,17 +1527,17 @@ describe('ValidatorShareLegacy', function () { }) }) - it('Bob must claim 3000 stake', async function () { + it('Bob must claim 3000 pol', async function () { assertBigNumberEquality( - await this.stakeToken.balanceOf(this.bob), - toWei('3000') + await this.polToken.balanceOf(this.bob), + initialBobPolBalance.add(toWei('3000')) ) }) - it('Bob must have unchanged legacy', async function () { + it('Bob must have unchanged pol', async function () { assertBigNumberEquality( - await this.legacyToken.balanceOf(this.bob), - initialBobMaticBalance + await this.stakeToken.balanceOf(this.bob), + initialBobStakeBalance ) }) @@ -1549,13 +1554,13 @@ describe('ValidatorShareLegacy', function () { before('Alice purchases voucher', async function () { initialAliceSharesBalance = await this.validatorContract.balanceOf(this.alice) - await buyVoucherLegacy(this.validatorContract, ValidatorDefaultStake, this.alice) + await buyVoucherPOL(this.validatorContract, ValidatorDefaultStake, this.alice) }) it('reverts', async function () { const validatorAlice = this.validatorContract.connect(this.validatorContract.provider.getSigner(this.alice)) await expectRevert.unspecified( - validatorAlice.transfer(ZeroAddr, initialAliceSharesBalance) + validatorAlice.transferPOL(ZeroAddr, initialAliceSharesBalance) ) }) }) @@ -1620,7 +1625,7 @@ function shouldWithdrawReward({ initialBalance, validatorId, user, reward, check if (checkBalance) { it('must have updated balance', async function () { - const balance = await this.legacyToken.balanceOf(user || this.user) + const balance = await this.polToken.balanceOf(user || this.user) assertBigNumberEquality(balance, new BN(initialBalance).add(new BN(reward))) }) } diff --git a/test/units/staking/deployment.js b/test/units/staking/deployment.js index 8eba92e7..9b28735b 100644 --- a/test/units/staking/deployment.js +++ b/test/units/staking/deployment.js @@ -34,10 +34,10 @@ export const walletAmounts = { } } -export async function freshDeploy(legacy = false) { - let contracts = await deployer.deployStakeManager(wallets, legacy) +export async function freshDeploy(pol = false) { + let contracts = await deployer.deployStakeManager(wallets, pol) this.stakeToken = contracts.stakeToken - this.legacyToken = contracts.legacyToken + this.polToken = contracts.polToken this.stakeManager = contracts.stakeManager this.nftContract = contracts.stakingNFT this.rootChainOwner = contracts.rootChainOwner @@ -57,15 +57,11 @@ export async function freshDeploy(legacy = false) { for (const walletAddr in walletAmounts) { await this.stakeToken.mint(walletAddr, walletAmounts[walletAddr].initialBalance) - if (legacy) { - await this.legacyToken.mint(walletAddr, walletAmounts[walletAddr].initialBalance) + if (pol) { + await this.polToken.mint(walletAddr, walletAmounts[walletAddr].initialBalance) } } - if (!legacy) { - await this.stakeToken.mint(this.stakeManager.address, web3.utils.toWei('10000000')) - } - this.defaultHeimdallFee = new BN(web3.utils.toWei('1')) } @@ -77,15 +73,15 @@ export async function approveAndStake({ heimdallFee, noMinting = false, signer, - legacy = false + pol = false }) { const fee = heimdallFee || this.defaultHeimdallFee const mintAmount = new BN(approveAmount || stakeAmount).add(new BN(fee)) let token - if (legacy) { - token = this.legacyToken + if (pol) { + token = this.polToken } else { token = this.stakeToken } @@ -106,8 +102,8 @@ export async function approveAndStake({ const stakeManagerWallet = this.stakeManager.connect(this.stakeManager.provider.getSigner(wallet.getAddressString())) - if (legacy) { - await stakeManagerWallet.stakeForLegacy( + if (pol) { + await stakeManagerWallet.stakeForPOL( wallet.getAddressString(), stakeAmount.toString(), fee.toString(), @@ -123,5 +119,4 @@ export async function approveAndStake({ signer || wallet.getPublicKeyString() ) } - } diff --git a/test/units/staking/stakeManager/StakeManager.Staking.js b/test/units/staking/stakeManager/StakeManager.Staking.js index 8d200656..29187610 100644 --- a/test/units/staking/stakeManager/StakeManager.Staking.js +++ b/test/units/staking/stakeManager/StakeManager.Staking.js @@ -42,7 +42,7 @@ export function doUnstake(wallet) { export function prepareForTest(dynastyValue, validatorThreshold) { return async function () { - await freshDeploy.call(this) + await freshDeploy.call(this, true) await this.governance.update( this.stakeManager.address, @@ -208,7 +208,9 @@ describe('stake', function () { } describe('double stake', async function () { - before(freshDeploy) + before(async function() { + await freshDeploy.call(this, true) + }) describe('when stakes first time', function () { const amounts = walletAmounts[wallets[1].getAddressString()] @@ -232,7 +234,9 @@ describe('stake', function () { }) describe('stake and restake following by another stake', function () { - before(freshDeploy) + before(async function() { + await freshDeploy.call(this, true) + }) const amounts = walletAmounts[wallets[2].getAddressString()] before('Stake', doStake(wallets[2])) @@ -259,12 +263,12 @@ describe('stake', function () { it('when auction is active', async function () { let auctionBid = web3.utils.toWei('10000') const auctionUser = wallets[4].getAddressString() - await this.stakeToken.mint(auctionUser, auctionBid) + await this.polToken.mint(auctionUser, auctionBid) - const stakeTokenUser = this.stakeToken.connect(this.stakeToken.provider.getSigner(auctionUser)) + const polTokenUser = this.polToken.connect(this.polToken.provider.getSigner(auctionUser)) const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(auctionUser)) - await stakeTokenUser.approve(this.stakeManager.address, auctionBid) + await polTokenUser.approve(this.stakeManager.address, auctionBid) const validatorId = await this.stakeManager.getValidatorId(wallets[2].getChecksumAddressString()) await stakeManagerUser.startAuction(validatorId, auctionBid, false, wallets[4].getPublicKeyString()) testRestake( @@ -304,7 +308,9 @@ describe('stake', function () { }) describe('consecutive stakes', function () { - before(freshDeploy) + before(async function() { + await freshDeploy.call(this, true) + }) it('validatorId must increment 1 by 1', async function () { const _wallets = [wallets[1], wallets[2], wallets[3]] @@ -322,7 +328,9 @@ describe('stake', function () { }) describe('stake with heimdall fee', function () { - before(freshDeploy) + before(async function() { + await freshDeploy.call(this, true) + }) testStake( wallets[0].getChecksumAddressString(), @@ -338,7 +346,9 @@ describe('stake', function () { const AliceWallet = wallets[1] const newSigner = wallets[2].getPublicKeyString() - before(freshDeploy) + before(async function() { + await freshDeploy.call(this, true) + }) before(doStake(AliceWallet)) before('Change signer', async function () { const signerUpdateLimit = await this.stakeManager.signerUpdateLimit() @@ -365,7 +375,9 @@ describe('unstake', function () { const AliceNewWallet = wallets[2] let stakeManagerAlice - before(freshDeploy) + before(async function() { + await freshDeploy.call(this, true) + }) before(doStake(AliceWallet)) before(doStake(BobWallet)) before('Change signer', async function () { @@ -546,7 +558,9 @@ describe('unstake', function () { }) describe('reverts', function () { - beforeEach('Fresh Deploy', freshDeploy) + beforeEach('Fresh Deploy', async function() { + await freshDeploy.call(this, true) + }) const user = wallets[2].getChecksumAddressString() let stakeManagerUser @@ -575,12 +589,12 @@ describe('unstake', function () { it('when unstakes during auction', async function () { const amount = web3.utils.toWei('1200').toString() const auctionUser = wallets[4].getAddressString() - await this.stakeToken.mint(auctionUser, amount) + await this.polToken.mint(auctionUser, amount) - const stakeTokenAuctionUser = this.stakeToken.connect(this.stakeToken.provider.getSigner(auctionUser)) + const polTokenAuctionUser = this.polToken.connect(this.polToken.provider.getSigner(auctionUser)) const stakeManagerAuctionUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(auctionUser)) - await stakeTokenAuctionUser.approve(this.stakeManager.address, amount) + await polTokenAuctionUser.approve(this.stakeManager.address, amount) const validatorId = await this.stakeManager.getValidatorId(user) await stakeManagerAuctionUser.startAuction(validatorId, amount, false, wallets[4].getPublicKeyString()) await expectRevert.unspecified(stakeManagerUser.unstake(validatorId)) diff --git a/test/units/staking/stakeManager/StakeManager.StakingLegacy.js b/test/units/staking/stakeManager/StakeManager.StakingPol.js similarity index 84% rename from test/units/staking/stakeManager/StakeManager.StakingLegacy.js rename to test/units/staking/stakeManager/StakeManager.StakingPol.js index f3fec738..e9f96b97 100644 --- a/test/units/staking/stakeManager/StakeManager.StakingLegacy.js +++ b/test/units/staking/stakeManager/StakeManager.StakingPol.js @@ -25,7 +25,7 @@ export function doStake( acceptDelegation, noMinting, signer, - legacy: true + pol: true }) } } @@ -37,7 +37,7 @@ export function doUnstake(wallet) { const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) const validatorId = await this.stakeManager.getValidatorId(user) - await stakeManagerUser.unstakeLegacy(validatorId) + await stakeManagerUser.unstakePOL(validatorId) } } @@ -58,12 +58,12 @@ export function prepareForTest(dynastyValue, validatorThreshold) { } describe('migrate matic', function (){ - describe('initializeLegacy', function(){ + describe('initializePOL', function(){ before('Setup migration scenario', async function() { await freshDeploy.call(this) }) - describe('must revert with legacy functions', function(){ + describe('must revert with pol functions', function(){ let stakeTokenUser, user, stakeManagerUser, amount, userPubkey before('', async function(){ userPubkey = wallets[1].getPublicKeyString(), @@ -76,12 +76,12 @@ describe('migrate matic', function (){ it('on stake token', async function () { await stakeTokenUser.approve(this.stakeManager.address, amount.toString()) - await expect(stakeManagerUser.stakeForLegacy(user, amount.toString(), web3.utils.toWei('1'), false, userPubkey)) - .to.be.rejectedWith('function call to a non-contract account') + await expect(stakeManagerUser.stakeForPOL(user, amount.toString(), web3.utils.toWei('1'), false, userPubkey)) + .to.be.rejectedWith('') }) }) - describe('run initializeLegacy', function(){ + describe('run initializePOL', function(){ let oldStakeToken, newStakeToken, migrationAmount before('gov update', async function(){ migrationAmount = web3.utils.toWei('20000000') @@ -101,16 +101,16 @@ describe('migrate matic', function (){ await newStakeToken.mint(this.migration.address, web3.utils.toWei('50000000')) }) - it('must initLegacy', async function () { + it('must initializePOL', async function () { await this.governance.update( this.stakeManager.address, - this.stakeManager.interface.encodeFunctionData('initializeLegacy', [newStakeToken.address, this.migration.address]) + this.stakeManager.interface.encodeFunctionData('initializePOL', [newStakeToken.address, this.migration.address]) ) }) - it('stakemanager must have correct legacy balance', async function () { - let legacyBalance = await oldStakeToken.balanceOf(this.stakeManager.address) - assertBigNumberEquality(BN(0), legacyBalance) + it('stakemanager must have correct pol balance', async function () { + let polBalance = await oldStakeToken.balanceOf(this.stakeManager.address) + assertBigNumberEquality(BN(0), polBalance) }) it('stakemanager must have correct stake balance', async function () { @@ -122,39 +122,39 @@ describe('migrate matic', function (){ describe('successful migration', function(){ const migrationAmount = new BN('100000000000000') - const initalLegacyAmount = new BN('100000000000000') + const initalPolAmount = new BN('100000000000000') const initalStakeAmount = new BN(0) before('Setup migration scenario', async function() { await freshDeploy.call(this) this.stakeToken = await TestToken.deploy('POL', 'POL') - this.legacyToken = await TestToken.deploy('MATIC', 'MATIC') + this.polToken = await TestToken.deploy('MATIC', 'MATIC') - this.migration = await PolygonMigration.deploy(this.legacyToken.address, this.stakeToken.address) + this.migration = await PolygonMigration.deploy(this.polToken.address, this.stakeToken.address) await this.governance.update( this.stakeManager.address, - this.stakeManager.interface.encodeFunctionData('setStakingToken', [this.legacyToken.address]) + this.stakeManager.interface.encodeFunctionData('setStakingToken', [this.polToken.address]) ) await this.governance.update( this.stakeManager.address, - this.stakeManager.interface.encodeFunctionData('initializeLegacy', [this.stakeToken.address, this.migration.address]) + this.stakeManager.interface.encodeFunctionData('initializePOL', [this.stakeToken.address, this.migration.address]) ) await this.stakeToken.mint(this.stakeManager.address, initalStakeAmount.toString()) - await this.legacyToken.mint(this.stakeManager.address, initalLegacyAmount.toString()) + await this.polToken.mint(this.stakeManager.address, initalPolAmount.toString()) await this.stakeToken.mint(this.migration.address, web3.utils.toWei('50000000')) - await this.legacyToken.mint(this.migration.address, web3.utils.toWei('50000000')) + await this.polToken.mint(this.migration.address, web3.utils.toWei('50000000')) }) it('must revert with too many token', async function () { - const bigAmount = initalLegacyAmount.mul(new BN('20')) + const bigAmount = initalPolAmount.mul(new BN('20')) await expectRevert( this.governance.update( this.stakeManager.address, - this.stakeManager.interface.encodeFunctionData('convertMaticToPol', [bigAmount.toString()]) + this.stakeManager.interface.encodeFunctionData('convertMaticToPOL', [bigAmount.toString()]) ), 'Update failed') //'Insufficient MATIC balance' }) @@ -162,12 +162,12 @@ describe('migrate matic', function (){ it('must migrate', async function () { await this.governance.update( this.stakeManager.address, - this.stakeManager.interface.encodeFunctionData('convertMaticToPol', [migrationAmount.toString()]) + this.stakeManager.interface.encodeFunctionData('convertMaticToPOL', [migrationAmount.toString()]) ) }) - it('must have correct legacy balance', async function(){ - const legacyBalance = await this.legacyToken.balanceOf(this.stakeManager.address) - assertBigNumberEquality(legacyBalance, initalLegacyAmount.sub(migrationAmount)) + it('must have correct pol balance', async function(){ + const polBalance = await this.polToken.balanceOf(this.stakeManager.address) + assertBigNumberEquality(polBalance, initalPolAmount.sub(migrationAmount)) }) it('must have correct stake balance', async function(){ @@ -178,28 +178,28 @@ describe('migrate matic', function (){ }) -describe('stake Legacy', function () { +describe('stake POL', function () { function testStakeRevert(user, userPubkey, amount, stakeAmount, unspecified = false) { - let stakeTokenUser, stakeManagerUser, legacyTokenUser + let stakeManagerUser, polTokenUser before('Approve', async function () { this.initialBalance = await this.stakeManager.totalStakedFor(user) - legacyTokenUser = this.legacyToken.connect(this.legacyToken.provider.getSigner(user)) + polTokenUser = this.polToken.connect(this.polToken.provider.getSigner(user)) stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) - await legacyTokenUser.approve(this.stakeManager.address, new BN(amount).add(this.defaultHeimdallFee).toString()) + await polTokenUser.approve(this.stakeManager.address, new BN(amount).add(this.defaultHeimdallFee).toString()) }) it('must revert', async function () { if (unspecified) { await expectRevert( - stakeManagerUser.stakeForLegacy(user, stakeAmount, this.defaultHeimdallFee.toString(), false, userPubkey), + stakeManagerUser.stakeForPOL(user, stakeAmount, this.defaultHeimdallFee.toString(), false, userPubkey), 'no more slots' ) } else { await expectRevert( - stakeManagerUser.stakeForLegacy(user, stakeAmount, this.defaultHeimdallFee.toString(), false, userPubkey), + stakeManagerUser.stakeForPOL(user, stakeAmount, this.defaultHeimdallFee.toString(), false, userPubkey), 'Invalid signer' ) } @@ -212,20 +212,20 @@ describe('stake Legacy', function () { } function testStake(user, userPubkey, amount, stakeAmount, validatorId, fee) { - let stakeTokenUser, stakeManagerUser, legacyTokenUser + let stakeManagerUser, polTokenUser before('Approve', async function () { this.user = user this.fee = new BN(fee || this.defaultHeimdallFee) - legacyTokenUser = this.legacyToken.connect(this.legacyToken.provider.getSigner(user)) + polTokenUser = this.polToken.connect(this.polToken.provider.getSigner(user)) stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) - await legacyTokenUser.approve(this.stakeManager.address, new BN(amount).add(this.fee).toString()) + await polTokenUser.approve(this.stakeManager.address, new BN(amount).add(this.fee).toString()) }) it('must stake', async function () { this.receipt = await ( - await stakeManagerUser.stakeForLegacy(user, stakeAmount.toString(), this.fee.toString(), false, userPubkey) + await stakeManagerUser.stakeForPOL(user, stakeAmount.toString(), this.fee.toString(), false, userPubkey) ).wait() }) @@ -270,41 +270,41 @@ describe('stake Legacy', function () { it('must pay out rewards correctly', async function () { const validatorId = await this.stakeManager.getValidatorId(user) const reward = await this.stakeManager.validatorReward(validatorId) - const balanceBefore = await this.legacyToken.balanceOf(user) + const balanceBefore = await this.polToken.balanceOf(user) assertBigNumberEquality(reward, new BN(0)) await checkPoint(wallets, this.rootChainOwner, this.stakeManager) await checkPoint(wallets, this.rootChainOwner, this.stakeManager) const newReward = await this.stakeManager.validatorReward(validatorId) assertBigNumbergt(newReward, reward) - await stakeManagerUser.withdrawRewardsLegacy(validatorId) - const balanceAfter = await this.legacyToken.balanceOf(user) + await stakeManagerUser.withdrawRewardsPOL(validatorId) + const balanceAfter = await this.polToken.balanceOf(user) assertBigNumberEquality(balanceAfter.sub(balanceBefore), newReward) await checkPoint(wallets, this.rootChainOwner, this.stakeManager) await checkPoint(wallets, this.rootChainOwner, this.stakeManager) const newReward2 = await this.stakeManager.validatorReward(validatorId) - await stakeManagerUser.withdrawRewardsLegacy(validatorId) - const balanceAfter2 = await this.legacyToken.balanceOf(user) + await stakeManagerUser.withdrawRewardsPOL(validatorId) + const balanceAfter2 = await this.polToken.balanceOf(user) assertBigNumberEquality(balanceAfter2.sub(balanceAfter), newReward2) assertBigNumberEquality(newReward2, newReward) }) } function testRestake(user, amount, stakeAmount, restakeAmount, totalStaked) { - let stakeTokenUser, stakeManagerUser, legacyTokenUser + let stakeManagerUser, polTokenUser before('Approve', async function () { this.user = user - legacyTokenUser = this.legacyToken.connect(this.legacyToken.provider.getSigner(user)) + polTokenUser = this.polToken.connect(this.polToken.provider.getSigner(user)) stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) - await legacyTokenUser.approve(this.stakeManager.address, amount.toString()) + await polTokenUser.approve(this.stakeManager.address, amount.toString()) }) it('must restake', async function () { const validatorId = await this.stakeManager.getValidatorId(this.user) - this.receipt = await (await stakeManagerUser.restakeLegacy(validatorId, restakeAmount, false)).wait() + this.receipt = await (await stakeManagerUser.restakePOL(validatorId, restakeAmount, false)).wait() }) it('must emit StakeUpdate', async function () { @@ -385,12 +385,12 @@ describe('stake Legacy', function () { it('when auction is active', async function () { let auctionBid = web3.utils.toWei('10000') const auctionUser = wallets[4].getAddressString() - await this.stakeToken.mint(auctionUser, auctionBid) + await this.polToken.mint(auctionUser, auctionBid) - const stakeTokenUser = this.stakeToken.connect(this.stakeToken.provider.getSigner(auctionUser)) + const polTokenUser = this.polToken.connect(this.polToken.provider.getSigner(auctionUser)) const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(auctionUser)) - await stakeTokenUser.approve(this.stakeManager.address, auctionBid) + await polTokenUser.approve(this.stakeManager.address, auctionBid) const validatorId = await this.stakeManager.getValidatorId(wallets[2].getChecksumAddressString()) await stakeManagerUser.startAuction(validatorId, auctionBid, false, auctionUser) testRestake( @@ -490,7 +490,7 @@ describe('stake Legacy', function () { }) }) -describe('unstake Legacy', function () { +describe('unstake POL', function () { describe('when Alice unstakes and update the signer', function () { const AliceWallet = wallets[1] const BobWallet = wallets[3] @@ -514,7 +514,7 @@ describe('unstake Legacy', function () { }) it('Alice should unstake', async function () { - this.receipt = await stakeManagerAlice.unstakeLegacy(this.validatorId) + this.receipt = await stakeManagerAlice.unstakePOL(this.validatorId) }) it("Signers list should have only Bob's signer", async function () { @@ -544,13 +544,13 @@ describe('unstake Legacy', function () { const reward = await this.stakeManager.validatorReward(this.validatorId) this.reward = reward - this.afterStakeBalance = await this.legacyToken.balanceOf(user) + this.afterStakeBalance = await this.polToken.balanceOf(user) stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) }) it('must unstake', async function () { - this.receipt = await (await stakeManagerUser.unstakeLegacy(this.validatorId)).wait() + this.receipt = await (await stakeManagerUser.unstakePOL(this.validatorId)).wait() }) it('must emit UnstakeInit', async function () { @@ -577,7 +577,7 @@ describe('unstake Legacy', function () { }) it('must have increased balance by reward', async function () { - const balance = await this.legacyToken.balanceOf(user) + const balance = await this.polToken.balanceOf(user) assertBigNumberEquality(balance, this.afterStakeBalance.add(this.reward)) }) }) @@ -595,17 +595,17 @@ describe('unstake Legacy', function () { before(async function () { this.validatorId = await this.stakeManager.getValidatorId(user) - const legacyToken4 = this.legacyToken.connect(this.legacyToken.provider.getSigner(wallets[4].getAddressString())) + const polToken4 = this.polToken.connect(this.polToken.provider.getSigner(wallets[4].getAddressString())) stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) // delegate tokens to validator const validatorShareAddr = await this.stakeManager.getValidatorContract(this.validatorId) - await legacyToken4.approve(this.stakeManager.address, web3.utils.toWei('100')) + await polToken4.approve(this.stakeManager.address, web3.utils.toWei('100')) const validator = await ValidatorShare.attach(validatorShareAddr) const validator4 = validator.connect(validator.provider.getSigner(wallets[4].getAddressString())) - await validator4.buyVoucherLegacy(web3.utils.toWei('100'), 0) + await validator4.buyVoucherPOL(web3.utils.toWei('100'), 0) - this.afterStakeBalance = await this.legacyToken.balanceOf(user) + this.afterStakeBalance = await this.polToken.balanceOf(user) }) before(async function () { @@ -618,7 +618,7 @@ describe('unstake Legacy', function () { it('must unstake', async function () { const validatorId = await this.stakeManager.getValidatorId(user) - this.receipt = await (await stakeManagerUser.unstakeLegacy(validatorId)).wait() + this.receipt = await (await stakeManagerUser.unstakePOL(validatorId)).wait() }) it('must emit UnstakeInit', async function () { @@ -646,7 +646,7 @@ describe('unstake Legacy', function () { }) it('must have increased balance by reward', async function () { - const balance = await this.legacyToken.balanceOf(user) + const balance = await this.polToken.balanceOf(user) assertBigNumberEquality(balance, this.afterStakeBalance.add(this.reward)) }) @@ -666,13 +666,13 @@ describe('unstake Legacy', function () { assertBigNumbergt(validatorRewardsAfter, validatorRewardsBefore) assertBigNumbergt(delegationRewardsAfter, delegationRewardsBefore) - await stakeManagerUser.withdrawRewardsLegacy(validatorId) - const balanceBefore = await this.legacyToken.balanceOf(user) + await stakeManagerUser.withdrawRewardsPOL(validatorId) + const balanceBefore = await this.polToken.balanceOf(user) await checkPoint([wallets[2]], this.rootChainOwner, this.stakeManager) - await stakeManagerUser.withdrawRewardsLegacy(validatorId) - assertBigNumberEquality(await this.legacyToken.balanceOf(user), balanceBefore) + await stakeManagerUser.withdrawRewardsPOL(validatorId) + assertBigNumberEquality(await this.polToken.balanceOf(user), balanceBefore) assertBigNumberEquality(await this.stakeManager.validatorReward(validatorId), new BN(0)) assertBigNumberEquality(await this.stakeManager.delegatorsReward(validatorId), delegationRewardsAfter) @@ -691,39 +691,39 @@ describe('unstake Legacy', function () { it('when validatorId is invalid', async function () { stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) - await expectRevert.unspecified(stakeManagerUser.unstakeLegacy('999999')) + await expectRevert.unspecified(stakeManagerUser.unstakePOL('999999')) }) it('when user is not staker', async function () { const validatorId = await this.stakeManager.getValidatorId(user) const stakeManager3 = this.stakeManager.connect(this.stakeManager.provider.getSigner(3)) - await expectRevert.unspecified(stakeManager3.unstakeLegacy(validatorId)) + await expectRevert.unspecified(stakeManager3.unstakePOL(validatorId)) }) it('when unstakes 2 times', async function () { const validatorId = await this.stakeManager.getValidatorId(user) - await stakeManagerUser.unstakeLegacy(validatorId) + await stakeManagerUser.unstakePOL(validatorId) - await expectRevert.unspecified(stakeManagerUser.unstakeLegacy(validatorId)) + await expectRevert.unspecified(stakeManagerUser.unstakePOL(validatorId)) }) it('when unstakes during auction', async function () { const amount = web3.utils.toWei('1200').toString() const auctionUser = wallets[4].getAddressString() - await this.stakeToken.mint(auctionUser, amount) + await this.polToken.mint(auctionUser, amount) - const stakeTokenAuctionUser = this.stakeToken.connect(this.stakeToken.provider.getSigner(auctionUser)) + const polTokenAuctionUser = this.polToken.connect(this.polToken.provider.getSigner(auctionUser)) const stakeManagerAuctionUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(auctionUser)) - await stakeTokenAuctionUser.approve(this.stakeManager.address, amount) + await polTokenAuctionUser.approve(this.stakeManager.address, amount) const validatorId = await this.stakeManager.getValidatorId(user) await stakeManagerAuctionUser.startAuction(validatorId, amount, false, wallets[4].getPublicKeyString()) - await expectRevert.unspecified(stakeManagerUser.unstakeLegacy(validatorId)) + await expectRevert.unspecified(stakeManagerUser.unstakePOL(validatorId)) }) }) }) -describe('unstakeClaim Legacy', function () { +describe('unstakeClaim POL', function () { describe('when user claims right after stake', function () { before('Fresh Deploy', prepareForTest(1, 10)) before('Stake', doStake(wallets[2])) @@ -734,7 +734,7 @@ describe('unstakeClaim Legacy', function () { it('must revert', async function () { const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) const ValidatorId = await this.stakeManager.getValidatorId(user) - await expect(stakeManagerUser.unstakeClaimLegacy(ValidatorId)) + await expect(stakeManagerUser.unstakeClaimPOL(ValidatorId)) }) }) @@ -761,7 +761,7 @@ describe('unstakeClaim Legacy', function () { }) it('must claim', async function () { - this.receipt = await (await stakeManagerAlice.unstakeClaimLegacy(this.validatorId)).wait() + this.receipt = await (await stakeManagerAlice.unstakeClaimPOL(this.validatorId)).wait() }) it('must emit Unstaked', async function () { @@ -798,7 +798,7 @@ describe('unstakeClaim Legacy', function () { it('must revert', async function () { const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) const validatorId = await this.stakeManager.getValidatorId(user) - await expect(stakeManagerUser.unstakeClaimLegacy(validatorId)) + await expect(stakeManagerUser.unstakeClaimPOL(validatorId)) }) }) @@ -820,7 +820,7 @@ describe('unstakeClaim Legacy', function () { it('must revert', async function () { const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) const validatorId = await this.stakeManager.getValidatorId(user) - await expect(stakeManagerUser.unstakeClaimLegacy(validatorId)) + await expect(stakeManagerUser.unstakeClaimPOL(validatorId)) }) }) @@ -851,7 +851,7 @@ describe('unstakeClaim Legacy', function () { const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) this.validatorId = await this.stakeManager.getValidatorId(user) this.reward = await this.stakeManager.validatorReward(this.validatorId) - this.receipt = await (await stakeManagerUser.unstakeClaimLegacy(this.validatorId)).wait() + this.receipt = await (await stakeManagerUser.unstakeClaimPOL(this.validatorId)).wait() }) it('must have correct reward', async function () { @@ -867,7 +867,7 @@ describe('unstakeClaim Legacy', function () { }) it('must have pre-stake + reward - heimdall fee balance', async function () { - let balance = await this.legacyToken.balanceOf(user) + let balance = await this.polToken.balanceOf(user) assertBigNumberEquality( balance, new BN(walletAmounts[user].initialBalance).add(new BN(this.reward.toString())).sub(this.defaultHeimdallFee) @@ -882,7 +882,7 @@ describe('unstakeClaim Legacy', function () { const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) this.validatorId = await this.stakeManager.getValidatorId(user) this.reward = await this.stakeManager.validatorReward(this.validatorId) - this.receipt = await (await stakeManagerUser.unstakeClaimLegacy(this.validatorId)).wait() + this.receipt = await (await stakeManagerUser.unstakeClaimPOL(this.validatorId)).wait() }) it('must have correct reward', async function () { @@ -898,7 +898,7 @@ describe('unstakeClaim Legacy', function () { }) it('must have pre-stake + reward - heimdall fee balance', async function () { - let balance = await this.legacyToken.balanceOf(user) + let balance = await this.polToken.balanceOf(user) assertBigNumberEquality( balance, new BN(walletAmounts[user].initialBalance).add(new BN(this.reward.toString())).sub(this.defaultHeimdallFee) @@ -926,7 +926,7 @@ describe('unstakeClaim Legacy', function () { }) }) -describe('restake Legacy', function () { +describe('restake POL', function () { const initialStake = web3.utils.toWei('1000') const initialStakers = [wallets[0], wallets[1]] @@ -953,7 +953,7 @@ describe('restake Legacy', function () { ) for (const wallet of initialStakers) { - await approveAndStake.call(this, { wallet, stakeAmount: initialStake, acceptDelegation, legacy: true }) + await approveAndStake.call(this, { wallet, stakeAmount: initialStake, acceptDelegation, pol: true }) } // cooldown period @@ -972,9 +972,9 @@ describe('restake Legacy', function () { this.user = initialStakers[0].getAddressString() this.amount = web3.utils.toWei('100') - await this.legacyToken.mint(this.user, this.amount) - this.legacyTokenUser = this.legacyToken.connect(this.stakeToken.provider.getSigner(this.user)) - await this.legacyTokenUser.approve(this.stakeManager.address, this.amount) + await this.polToken.mint(this.user, this.amount) + this.polTokenUser = this.polToken.connect(this.polToken.provider.getSigner(this.user)) + await this.polTokenUser.approve(this.stakeManager.address, this.amount) } } @@ -994,7 +994,7 @@ describe('restake Legacy', function () { it('must restake rewards', async function () { const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(this.user)) - this.receipt = await (await stakeManagerUser.restakeLegacy(this.validatorId, this.amount, withRewards)).wait() + this.receipt = await (await stakeManagerUser.restakePOL(this.validatorId, this.amount, withRewards)).wait() }) it('must emit StakeUpdate', async function () { @@ -1054,13 +1054,13 @@ describe('restake Legacy', function () { it('when validatorId is incorrect', async function () { const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(this.user)) - await expect(stakeManagerUser.restakeLegacy('0', this.amount, false)) + await expect(stakeManagerUser.restakePOL('0', this.amount, false)) }) it('when restake after unstake during same epoch', async function () { - await this.stakeManager.unstakeLegacy(this.validatorId) + await this.stakeManager.unstakePOL(this.validatorId) const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(this.user)) - await expectRevert(stakeManagerUser.restakeLegacy(this.validatorId, this.amount, false), 'No restaking') + await expectRevert(stakeManagerUser.restakePOL(this.validatorId, this.amount, false), 'No restaking') }) }) }) diff --git a/test/units/staking/stakeManager/StakeManager.test.js b/test/units/staking/stakeManager/StakeManager.test.js index debb75db..02c65321 100644 --- a/test/units/staking/stakeManager/StakeManager.test.js +++ b/test/units/staking/stakeManager/StakeManager.test.js @@ -104,15 +104,6 @@ describe('StakeManager', function (accounts) { async function batchDeploy() { await Staking.prepareForTest(4, 2).call(this) - this.stakeToken = await TestToken.deploy('MATIC', 'MATIC') - - await this.governance.update( - this.stakeManager.address, - this.stakeManager.interface.encodeFunctionData('setStakingToken', [this.stakeToken.address]) - ) - - await this.stakeToken.mint(this.stakeManager.address, web3.utils.toWei('10000000')) - this.validatorId = '1' this.validatorUser = wallets[0] this.stakeAmount = new BN(web3.utils.toWei('100')) @@ -284,7 +275,9 @@ describe('StakeManager', function (accounts) { let stakeAmount = web3.utils.toWei('100') function doDeploy(acceptDelegation) { - before('Fresh deploy', freshDeploy) + before('Fresh deploy', async function() { + await freshDeploy.call(this, true) + }) before('Approve and stake', async function () { await approveAndStake.call(this, { wallet: staker, stakeAmount: stakeAmount, acceptDelegation }) @@ -338,7 +331,9 @@ describe('StakeManager', function (accounts) { describe('checkSignatures', function () { function prepareToTest(stakers, checkpointBlockInterval = 1) { - before('Fresh deploy', freshDeploy) + before('Fresh deploy', async function(){ + await freshDeploy.call(this, true) + }) before('updateCheckPointBlockInterval', async function () { await this.governance.update( this.stakeManager.address, @@ -823,7 +818,9 @@ describe('StakeManager', function (accounts) { }) describe('when payload is invalid', function () { - beforeEach(freshDeploy) + beforeEach('Fresh deploy', async function(){ + await freshDeploy.call(this, true) + }) beforeEach('Prepare to test', async function () { this.amount = new BN(web3.utils.toWei('200')) this.wallets = [wallets[2]] @@ -923,7 +920,7 @@ describe('StakeManager', function (accounts) { } async function doDeploy() { - await freshDeploy.call(this) + await freshDeploy.call(this, true) this.checkpointIndex = 0 this.validators = [] @@ -987,7 +984,9 @@ describe('StakeManager', function (accounts) { }) describe("when trying to checkpoint when 1 of the validators unstakes with more than 1/3 stake and don't sign", function () { - before('Fresh Deploy', freshDeploy) + before('Fresh deploy', async function(){ + await freshDeploy.call(this, true) + }) before('Alice And Bob Stake', async function () { for (const wallet of [wallets[2], wallets[3]]) { await approveAndStake.call(this, { @@ -1010,8 +1009,9 @@ describe('StakeManager', function (accounts) { describe('dethroneAndStake', function () { describe('when from is not stake manager', function () { - before('Fresh Deploy', freshDeploy) - + before('Fresh deploy', async function(){ + await freshDeploy.call(this, true) + }) it('reverts', async function () { await expectRevert( this.stakeManager.dethroneAndStake( @@ -1030,7 +1030,9 @@ describe('StakeManager', function (accounts) { describe('setDelegationEnabled', function () { describe('when from is governance', function () { - before(freshDeploy) + before('Fresh deploy', async function(){ + await freshDeploy.call(this, true) + }) it('must disable delegation', async function () { await this.governance.update( @@ -1056,8 +1058,9 @@ describe('StakeManager', function (accounts) { }) describe('when from is not governance', function () { - before(freshDeploy) - + before('Fresh deploy', async function(){ + await freshDeploy.call(this, true) + }) it('reverts', async function () { await expectRevert(this.stakeManager.setDelegationEnabled(false), 'Only governance contract is authorized') }) @@ -1070,7 +1073,7 @@ describe('StakeManager', function (accounts) { const userOriginalPubKey = wallets[3].getPublicKeyString() async function doDeploy() { - await freshDeploy.call(this) + await freshDeploy.call(this, true) const amount = web3.utils.toWei('200') for (const wallet of w) { @@ -1273,7 +1276,9 @@ describe('StakeManager', function (accounts) { describe('updateDynastyValue', function () { describe('when set dynasty to 10', function () { - before(freshDeploy) + before('Fresh deploy', async function(){ + await freshDeploy.call(this, true) + }) it('must update dynasty', async function () { this.receipt = await ( @@ -1308,7 +1313,9 @@ describe('StakeManager', function (accounts) { }) describe('when set dynasty to 0', function () { - before(freshDeploy) + before('Fresh deploy', async function(){ + await freshDeploy.call(this, true) + }) it('must revert', async function () { await expectRevert.unspecified(this.stakeManager.updateDynastyValue('0')) @@ -1316,7 +1323,9 @@ describe('StakeManager', function (accounts) { }) describe('when from is not governance', function () { - before(freshDeploy) + before('Fresh deploy', async function(){ + await freshDeploy.call(this, true) + }) it('reverts', async function () { const stakeManagerOwner = this.stakeManager.connect(this.stakeManager.provider.getSigner(owner)) @@ -1327,7 +1336,9 @@ describe('StakeManager', function (accounts) { describe('updateCheckpointReward', function () { describe('when set reward to 20', function () { - before(freshDeploy) + before('Fresh deploy', async function(){ + await freshDeploy.call(this, true) + }) it('must update', async function () { this.oldReward = await this.stakeManager.CHECKPOINT_REWARD() @@ -1348,7 +1359,9 @@ describe('StakeManager', function (accounts) { }) describe('when set reward to 0', function () { - before(freshDeploy) + before('Fresh deploy', async function(){ + await freshDeploy.call(this, true) + }) it('must revert', async function () { await expectRevert.unspecified(this.stakeManager.updateCheckpointReward(0)) @@ -1356,7 +1369,9 @@ describe('StakeManager', function (accounts) { }) describe('when from is not governance', function () { - before(freshDeploy) + before('Fresh deploy', async function(){ + await freshDeploy.call(this, true) + }) it('reverts', async function () { const stakeManagerOwner = this.stakeManager.connect(this.stakeManager.provider.getSigner(owner)) @@ -1372,7 +1387,7 @@ describe('StakeManager', function (accounts) { let _wallets = [Alice, Bob] async function doDeploy() { - await freshDeploy.call(this) + await freshDeploy.call(this, true) this.amount = new BN(web3.utils.toWei('200')) this.totalStaked = new BN(0) @@ -1477,7 +1492,7 @@ describe('StakeManager', function (accounts) { const fee = new BN(web3.utils.toWei('50')).toString() async function doDeploy() { - await freshDeploy.call(this) + await freshDeploy.call(this, true) await approveAndStake.call(this, { wallet, stakeAmount: amount }) } @@ -1630,7 +1645,7 @@ describe('StakeManager', function (accounts) { } async function doDeploy() { - await freshDeploy.call(this) + await freshDeploy.call(this, true) this.checkpointIndex = 0 this.validators = [] @@ -1926,16 +1941,16 @@ describe('StakeManager', function (accounts) { before('deploy', doDeploy) before(async function () { - await this.stakeToken.mint(Alice.getAddressString(), aliceBidAmount) - const stakeTokenAlive = this.stakeToken.connect(this.stakeToken.provider.getSigner(Alice.getAddressString())) - await stakeTokenAlive.approve(this.stakeManager.address, aliceBidAmount) + await this.polToken.mint(Alice.getAddressString(), aliceBidAmount) + const polTokenAlice = this.polToken.connect(this.polToken.provider.getSigner(Alice.getAddressString())) + await polTokenAlice.approve(this.stakeManager.address, aliceBidAmount) - await this.stakeToken.mint(Bob.getAddressString(), bobBidAmount) - const stakeTokenBob = this.stakeToken.connect(this.stakeToken.provider.getSigner(Bob.getAddressString())) - await stakeTokenBob.approve(this.stakeManager.address, bobBidAmount) + await this.polToken.mint(Bob.getAddressString(), bobBidAmount) + const polTokenBob = this.polToken.connect(this.polToken.provider.getSigner(Bob.getAddressString())) + await polTokenBob.approve(this.stakeManager.address, bobBidAmount) - this.userOldBalance = await this.stakeToken.balanceOf(Alice.getAddressString()) - this.bobOldBalance = await this.stakeToken.balanceOf(Bob.getAddressString()) + this.userOldBalance = await this.polToken.balanceOf(Alice.getAddressString()) + this.bobOldBalance = await this.polToken.balanceOf(Bob.getAddressString()) this.validatorId = '1' this.initialStakeAmount = initialStakeAmount @@ -1949,7 +1964,7 @@ describe('StakeManager', function (accounts) { testStartAuction(Bob.getChecksumAddressString(), Bob.getPublicKeyString(), bobBidAmount) it('Alice must get her bid back', async function () { - const currentBalance = await this.stakeToken.balanceOf(Alice.getAddressString()) + const currentBalance = await this.polToken.balanceOf(Alice.getAddressString()) assertBigNumberEquality(this.userOldBalance, currentBalance) }) }) @@ -1974,8 +1989,8 @@ describe('StakeManager', function (accounts) { const stakeManager3 = this.stakeManager.connect(this.stakeManager.provider.getSigner(3)) await stakeManager3.startAuction(this.validatorId, this.amount, false, wallets[3].getPublicKeyString()) - const stakeToken3 = this.stakeToken.connect(this.stakeToken.provider.getSigner(3)) - await stakeToken3.approve(this.stakeManager.address, web3.utils.toWei('1')) + const polToken3 = this.polToken.connect(this.polToken.provider.getSigner(3)) + await polToken3.approve(this.stakeManager.address, web3.utils.toWei('1')) await expectRevert( stakeManager3.confirmAuctionBid(this.validatorId, web3.utils.toWei('1')), 'Not allowed before auctionPeriod' @@ -2062,12 +2077,12 @@ describe('StakeManager', function (accounts) { await checkPoint(_initialStakers, this.rootChainOwner, this.stakeManager) } this.amount = web3.utils.toWei('500') - const stakeToken3 = this.stakeToken.connect(this.stakeToken.provider.getSigner(3)) - await stakeToken3.approve(this.stakeManager.address, this.amount) + const polToken3 = this.polToken.connect(this.polToken.provider.getSigner(3)) + await polToken3.approve(this.stakeManager.address, this.amount) } }) - describe('confirmAuctionBid', function () { + describe.skip('confirmAuctionBid', function () { const initialStakers = [wallets[1], wallets[2]] const bidAmount = new BN(web3.utils.toWei('1200')) const initialStakeAmount = web3.utils.toWei('200') @@ -2084,15 +2099,15 @@ describe('StakeManager', function (accounts) { await approveAndStake.call(this, { wallet, stakeAmount: initialStakeAmount }) } - const stakeToken3 = this.stakeToken.connect(this.stakeToken.provider.getSigner(3)) + const polToken3 = this.polToken.connect(this.polToken.provider.getSigner(3)) this.amount = web3.utils.toWei('500') - await stakeToken3.approve(this.stakeManager.address, this.amount) + await polToken3.approve(this.stakeManager.address, this.amount) // bid const mintAmount = bidAmount.add(new BN(this.heimdallFee || this.defaultHeimdallFee)).toString() - await this.stakeToken.mint(this.bidder, mintAmount) - const stakeTokenBidder = this.stakeToken.connect(this.stakeToken.provider.getSigner(this.bidder)) - await stakeTokenBidder.approve(this.stakeManager.address, mintAmount) + await this.polToken.mint(this.bidder, mintAmount) + const polTokenBidder = this.polToken.connect(this.polToken.provider.getSigner(this.bidder)) + await polTokenBidder.approve(this.stakeManager.address, mintAmount) this.bidderBalanceBeforeAuction = await this.stakeToken.balanceOf(this.bidder) this.totalStakedBeforeAuction = await this.stakeManager.totalStaked() @@ -2273,12 +2288,12 @@ describe('StakeManager', function (accounts) { this.heimdallFee = this.defaultHeimdallFee const approveAmount = new BN(bidAmount).add(this.heimdallFee).toString() - await this.stakeToken.mint(auctionValidatorAddr, approveAmount) - const stakeTokenValidator = this.stakeToken.connect(this.stakeToken.provider.getSigner(auctionValidatorAddr)) - await stakeTokenValidator.approve(this.stakeManager.address, approveAmount) + await this.polToken.mint(auctionValidatorAddr, approveAmount) + const polTokenValidator = this.polToken.connect(this.polToken.provider.getSigner(auctionValidatorAddr)) + await polTokenValidator.approve(this.stakeManager.address, approveAmount) this.totalStakedBeforeAuction = await this.stakeManager.totalStaked() - this.bidderBalanceBeforeAuction = await this.stakeToken.balanceOf(auctionValidatorAddr) + this.bidderBalanceBeforeAuction = await this.polToken.balanceOf(auctionValidatorAddr) }) describe('when new validator bids', function () { @@ -2368,9 +2383,9 @@ describe('StakeManager', function (accounts) { }) it('must bid', async function () { - await this.stakeToken.mint(bidder, bidAmount) - const stakeToken3 = this.stakeToken.connect(this.stakeToken.provider.getSigner(3)) - await stakeToken3.approve(this.stakeManager.address, bidAmount) + await this.polToken.mint(bidder, bidAmount) + const polToken3 = this.polToken.connect(this.polToken.provider.getSigner(3)) + await polToken3.approve(this.stakeManager.address, bidAmount) const stakeManager3 = this.stakeManager.connect(this.stakeManager.provider.getSigner(3)) await stakeManager3.startAuction(this.validatorId, bidAmount, false, bidderPubKey) }) @@ -2398,7 +2413,7 @@ describe('StakeManager', function (accounts) { let stakeToken9, stakeManager9 async function prepareForTest() { - await freshDeploy.call(this) + await freshDeploy.call(this, true) stakeManager9 = this.stakeManager.connect(this.stakeManager.provider.getSigner(9)) stakeToken9 = this.stakeToken.connect(this.stakeToken.provider.getSigner(9)) await this.governance.update( @@ -2760,7 +2775,7 @@ describe('StakeManager', function (accounts) { }) it('balance must decrease by bid amount', async function () { - assertBigNumberEquality(await this.stakeToken.balanceOf(address), this.userOldBalance.sub(bidAmount).toString()) + assertBigNumberEquality(await this.polToken.balanceOf(address), this.userOldBalance.sub(bidAmount).toString()) }) } @@ -2808,7 +2823,7 @@ describe('StakeManager', function (accounts) { }) it('previous validator must get his reward', async function () { - let prevValidatorBalance = await this.stakeToken.balanceOf(this.prevValidatorAddr) + let prevValidatorBalance = await this.polToken.balanceOf(this.prevValidatorAddr) assertBigNumberEquality(prevValidatorBalance, this.prevValidatorOldBalance.add(this.reward)) }) @@ -2821,7 +2836,7 @@ describe('StakeManager', function (accounts) { }) it('bidder balance must be correct', async function () { - const currentBalance = await this.stakeToken.balanceOf(this.bidder) + const currentBalance = await this.polToken.balanceOf(this.bidder) assertBigNumberEquality( this.bidderBalanceBeforeAuction.sub(this.bidAmount.toString()).sub(this.heimdallFee.toString()), currentBalance From c22c9a2988508e3d091c9ca1cd59bc7153cc221c Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Sun, 7 Jul 2024 23:42:35 +0200 Subject: [PATCH 46/92] fix: topup with pol --- contracts/staking/stakeManager/StakeManager.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 523f8453..5f3041d7 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -349,7 +349,7 @@ contract StakeManager is Public Methods */ function topUpForFee(address user, uint256 heimdallFee) public onlyWhenUnlocked { - _transferAndTopUp(user, msg.sender, heimdallFee, 0, false); + _transferAndTopUp(user, msg.sender, heimdallFee, 0, true); } function claimFee(uint256 accumFeeAmount, uint256 index, bytes memory proof) public { From 00ba7e447b1df96e67d1d21e705a8ef7eeb9b04a Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Mon, 8 Jul 2024 12:57:43 +0200 Subject: [PATCH 47/92] feat: simple forktest --- scripts/helpers/generateInterfaces.sh | 19 ++++++++ test/ForkupgradeStakeManager.t.sol | 64 +++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100755 scripts/helpers/generateInterfaces.sh create mode 100644 test/ForkupgradeStakeManager.t.sol diff --git a/scripts/helpers/generateInterfaces.sh b/scripts/helpers/generateInterfaces.sh new file mode 100755 index 00000000..fc8a34c8 --- /dev/null +++ b/scripts/helpers/generateInterfaces.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +create_interface () { + contract="$(basename "$file" | cut -d. -f1)" + dir="$(dirname "$file")" + cast interface "$file" -n $contract > ./interfaces/$contract.generated.sol +} + +#forge build + +mkdir -p interfaces + +find ../../out -type f -print0 | while read -d $'\0' file +do + echo $file + create_interface +done + + diff --git a/test/ForkupgradeStakeManager.t.sol b/test/ForkupgradeStakeManager.t.sol new file mode 100644 index 00000000..e75406c6 --- /dev/null +++ b/test/ForkupgradeStakeManager.t.sol @@ -0,0 +1,64 @@ +pragma solidity ^0.8.4; + +import { StakeManager } from "../scripts/helpers/interfaces/StakeManager.generated.sol"; +import { StakeManagerProxy } from "../scripts/helpers/interfaces/StakeManagerProxy.generated.sol"; +import { ValidatorShare } from "../scripts/helpers/interfaces/ValidatorShare.generated.sol"; +import { Registry } from "../scripts/helpers/interfaces/Registry.generated.sol"; +import { ERC20 } from "../scripts/helpers/interfaces/ERC20.generated.sol"; + +import "forge-std/Test.sol"; + +contract ForkupgradeStakeManagerTest is Test { + uint256 mainnetFork; + + function setUp() public { + string memory MAINNET_RPC_URL = string.concat("https://mainnet.infura.io/v3/", vm.envString("INFURA_TOKEN")); + mainnetFork = vm.createFork(MAINNET_RPC_URL); + } + + function test_UpgradeStakeManager() public { + vm.selectFork(mainnetFork); + assertEq(vm.activeFork(), mainnetFork); + + StakeManager stakeManagerImpl; + stakeManagerImpl = StakeManager(deployCode("out/StakeManager.sol/StakeManager.json")); + + console.log("deployed StakeManager Implementation at: ", address(stakeManagerImpl)); + + ValidatorShare validatorShareImpl; + validatorShareImpl = ValidatorShare(deployCode("out/ValidatorShare.sol/ValidatorShare.json")); + + console.log("deployed ValidatorShare Implementation at: ", address(validatorShareImpl)); + + Registry registry = Registry(0x33a02E6cC863D393d6Bf231B697b82F6e499cA71); + console.log("found Registry at: ", address(registry)); + + StakeManager stakeManager = StakeManager(0x5e3Ef299fDDf15eAa0432E6e66473ace8c13D908); + StakeManagerProxy stakeManagerProxy = StakeManagerProxy(payable(0x5e3Ef299fDDf15eAa0432E6e66473ace8c13D908)); + console.log("found StakeManagerProxy at: ", address(stakeManagerProxy)); + + address governance = 0x6e7a5820baD6cebA8Ef5ea69c0C92EbbDAc9CE48; + address timelock = 0xCaf0aa768A3AE1297DF20072419Db8Bb8b5C8cEf; + ERC20 polToken = ERC20(0x455e53CBB86018Ac2B8092FdCd39d8444aFFC3F6); + ERC20 maticToken = ERC20(0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0); + address migration = 0x29e7DF7b6A1B2b07b731457f499E1696c60E2C4e; + + uint256 balance = maticToken.balanceOf(address(stakeManagerProxy)); + console.log("Matic balance: ", balance); + + // prank set registry as 0x6e7a5820baD6cebA8Ef5ea69c0C92EbbDAc9CE48 + vm.prank(governance); + registry.updateContractMap(keccak256("validatorShare"), address(validatorShareImpl)); + + // prank set proxyImpl as 0xCaf0aa768A3AE1297DF20072419Db8Bb8b5C8cEf + vm.prank(timelock); + stakeManagerProxy.updateImplementation(address(stakeManagerImpl)); + // prank call initPol with pol 0x455e53CBB86018Ac2B8092FdCd39d8444aFFC3F6 mig 0x29e7DF7b6A1B2b07b731457f499E1696c60E2C4e as 0x6e7a5820baD6cebA8Ef5ea69c0C92EbbDAc9CE48 + + vm.prank(governance); + stakeManager.initializePOL(address(polToken), migration); + + assertEq(maticToken.balanceOf(address(stakeManagerProxy)), 0); + assertEq(polToken.balanceOf(address(stakeManagerProxy)), balance); + } +} \ No newline at end of file From b3e78a586750a47619400ad9425bfd36e1b3c806 Mon Sep 17 00:00:00 2001 From: Simon Dosch Date: Fri, 12 Jul 2024 15:23:06 +0200 Subject: [PATCH 48/92] prepare forkTest --- .gitignore | 1 + .gitmodules | 5 ++++- foundry.toml | 8 ++++++-- lib/forge-std | 1 + package.json | 5 +++-- scripts/helpers/generateInterfaces.sh | 4 ++-- test/{ => foundry}/ForkupgradeStakeManager.t.sol | 13 ++++++------- 7 files changed, 23 insertions(+), 14 deletions(-) create mode 160000 lib/forge-std rename test/{ => foundry}/ForkupgradeStakeManager.t.sol (80%) diff --git a/.gitignore b/.gitignore index d3bc16ce..96b59fac 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ contractAddresses.json contracts/root/predicates/TransferWithSigUtils.sol contracts/common/mixin/ChainIdMixin.sol test/helpers/marketplaceUtils.js +scripts/helpers/interfaces cache_hardhat/ forge-cache/ diff --git a/.gitmodules b/.gitmodules index 3b131006..638b2891 100644 --- a/.gitmodules +++ b/.gitmodules @@ -9,4 +9,7 @@ url = https://github.com/0xPolygon/contract-deployer-template [submodule "lib/storage-layout-checker"] path = lib/storage-layout-checker - url = https://github.com/0xPolygon/storage-layout-checker \ No newline at end of file + url = https://github.com/0xPolygon/storage-layout-checker +[submodule "lib/forge-std"] + path = lib/forge-std + url = https://github.com/foundry-rs/forge-std diff --git a/foundry.toml b/foundry.toml index e0a6f2d5..f9674221 100644 --- a/foundry.toml +++ b/foundry.toml @@ -2,7 +2,7 @@ src = 'contracts' out = 'out' libs = ['node_modules'] -match-path = 'test/foundry' +no-match-path = 'test/foundry' optimizer = true optimizer_runs = 200 via_ir = true @@ -10,12 +10,16 @@ cache_path = 'forge-cache' verbosity = 2 solc_version = '0.5.17' ffi = true - remappings = [ "openzeppelin-solidity/=node_modules/openzeppelin-solidity/", "solidity-rlp/=node_modules/solidity-rlp/" ] +[profile.0_8_4] +solc_version = '0.8.4' +src = 'test' +libs = ["lib"] + [invariant] fail_on_revert = false call_override = false diff --git a/lib/forge-std b/lib/forge-std new file mode 160000 index 00000000..07263d19 --- /dev/null +++ b/lib/forge-std @@ -0,0 +1 @@ +Subproject commit 07263d193d621c4b2b0ce8b4d54af58f6957d97d diff --git a/package.json b/package.json index 35bd3d97..6b6f30e5 100644 --- a/package.json +++ b/package.json @@ -9,9 +9,10 @@ "test": "test" }, "scripts": { - "build": "forge build", + "build": "forge build --skip test", "test:hardhat": "npx hardhat test", - "test:foundry": "forge test", + "generate-interfaces": "scripts/helpers/generateInterfaces.sh", + "test:foundry": "export FOUNDRY_PROFILE=0_8_4 && forge test", "test:ci": "scripts/run-test.sh", "testrpc": "ganache --chain.hardfork istanbul --wallet.mnemonic 'clock radar mass judge dismiss just intact mind resemble fringe diary casino' -p 8545 --gasLimit 10000000 --gasPrice 0 --chain.allowUnlimitedContractSize --accounts 200", "template:process": "node scripts/process-templates.cjs", diff --git a/scripts/helpers/generateInterfaces.sh b/scripts/helpers/generateInterfaces.sh index fc8a34c8..1396a40e 100755 --- a/scripts/helpers/generateInterfaces.sh +++ b/scripts/helpers/generateInterfaces.sh @@ -3,14 +3,14 @@ create_interface () { contract="$(basename "$file" | cut -d. -f1)" dir="$(dirname "$file")" - cast interface "$file" -n $contract > ./interfaces/$contract.generated.sol + cast interface "$file" -n $contract > scripts/helpers/interfaces/$contract.generated.sol } #forge build mkdir -p interfaces -find ../../out -type f -print0 | while read -d $'\0' file +find out -type f -print0 | while read -d $'\0' file do echo $file create_interface diff --git a/test/ForkupgradeStakeManager.t.sol b/test/foundry/ForkupgradeStakeManager.t.sol similarity index 80% rename from test/ForkupgradeStakeManager.t.sol rename to test/foundry/ForkupgradeStakeManager.t.sol index e75406c6..1a8e1a88 100644 --- a/test/ForkupgradeStakeManager.t.sol +++ b/test/foundry/ForkupgradeStakeManager.t.sol @@ -1,10 +1,10 @@ pragma solidity ^0.8.4; -import { StakeManager } from "../scripts/helpers/interfaces/StakeManager.generated.sol"; -import { StakeManagerProxy } from "../scripts/helpers/interfaces/StakeManagerProxy.generated.sol"; -import { ValidatorShare } from "../scripts/helpers/interfaces/ValidatorShare.generated.sol"; -import { Registry } from "../scripts/helpers/interfaces/Registry.generated.sol"; -import { ERC20 } from "../scripts/helpers/interfaces/ERC20.generated.sol"; +import { StakeManager } from "../../scripts/helpers/interfaces/StakeManager.generated.sol"; +import { StakeManagerProxy } from "../../scripts/helpers/interfaces/StakeManagerProxy.generated.sol"; +import { ValidatorShare } from "../../scripts/helpers/interfaces/ValidatorShare.generated.sol"; +import { Registry } from "../../scripts/helpers/interfaces/Registry.generated.sol"; +import { ERC20 } from "../../scripts/helpers/interfaces/ERC20.generated.sol"; import "forge-std/Test.sol"; @@ -12,8 +12,7 @@ contract ForkupgradeStakeManagerTest is Test { uint256 mainnetFork; function setUp() public { - string memory MAINNET_RPC_URL = string.concat("https://mainnet.infura.io/v3/", vm.envString("INFURA_TOKEN")); - mainnetFork = vm.createFork(MAINNET_RPC_URL); + mainnetFork = vm.createFork(vm.rpcUrl("mainnet")); } function test_UpgradeStakeManager() public { From 4b864a4964ff3489ee6f5442826b1241f2806e09 Mon Sep 17 00:00:00 2001 From: Simon Dosch Date: Fri, 12 Jul 2024 18:10:12 +0200 Subject: [PATCH 49/92] fix tests --- test/units/staking/stakeManager/StakeManager.test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/units/staking/stakeManager/StakeManager.test.js b/test/units/staking/stakeManager/StakeManager.test.js index 02c65321..70876cdd 100644 --- a/test/units/staking/stakeManager/StakeManager.test.js +++ b/test/units/staking/stakeManager/StakeManager.test.js @@ -1498,8 +1498,8 @@ describe('StakeManager', function (accounts) { function testTopUp(user) { it('must top up', async function () { - const stakeTokenUser = this.stakeToken.connect(this.stakeToken.provider.getSigner(user)) - await stakeTokenUser.approve(this.stakeManager.address, fee) + const stakeTokenUser = this.polToken.connect(this.polToken.provider.getSigner(user)) + await (await stakeTokenUser.approve(this.stakeManager.address, fee)).wait() const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(user)) this.receipt = await (await stakeManagerUser.topUpForFee(user, fee)).wait() @@ -1683,7 +1683,7 @@ describe('StakeManager', function (accounts) { ) } - const stakeTokenValidatorUser = this.stakeToken.connect(this.stakeToken.provider.getSigner(validatorAddr)) + const stakeTokenValidatorUser = this.polToken.connect(this.polToken.provider.getSigner(validatorAddr)) await stakeTokenValidatorUser.approve(this.stakeManager.address, fee.toString()) const stakeManagerValidatorUser = this.stakeManager.connect( @@ -1741,7 +1741,7 @@ describe('StakeManager', function (accounts) { before('top up', async function () { this.user = this.validatorsWallets[AliceValidatorId].getChecksumAddressString() - const stakeTokenUser = this.stakeToken.connect(this.stakeToken.provider.getSigner(this.user)) + const stakeTokenUser = this.polToken.connect(this.polToken.provider.getSigner(this.user)) await stakeTokenUser.approve(this.stakeManager.address, totalFee) const stakeManagerUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(this.user)) From e7cd12ac8a45abd83b89883b92aae4792dc24043 Mon Sep 17 00:00:00 2001 From: Simon Dosch Date: Sun, 14 Jul 2024 14:15:33 +0200 Subject: [PATCH 50/92] work on ci --- .github/workflows/ci.yml | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4d7d854e..f981c47f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,9 +43,9 @@ jobs: - name: Run Forge build run: | forge --version - forge build --sizes + forge build --sizes --skip test id: build - name: Run Forge tests - run: if test -d test/foundry && find test/foundry -name '*.sol' | grep -q .; then forge test -vvv; else echo "No .sol files found in test/foundry directory. Skipping Forge tests."; fi + run: if test -d test/foundry && find test/foundry -name '*.sol' | grep -q .; then FOUNDRY_PROFILE=0_8_4 forge test -vvv; else echo "No .sol files found in test/foundry directory. Skipping Forge tests."; fi id: test diff --git a/package.json b/package.json index 6b6f30e5..35dd8b64 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "build": "forge build --skip test", "test:hardhat": "npx hardhat test", "generate-interfaces": "scripts/helpers/generateInterfaces.sh", - "test:foundry": "export FOUNDRY_PROFILE=0_8_4 && forge test", + "test:foundry": "FOUNDRY_PROFILE=0_8_4 forge test", "test:ci": "scripts/run-test.sh", "testrpc": "ganache --chain.hardfork istanbul --wallet.mnemonic 'clock radar mass judge dismiss just intact mind resemble fringe diary casino' -p 8545 --gasLimit 10000000 --gasPrice 0 --chain.allowUnlimitedContractSize --accounts 200", "template:process": "node scripts/process-templates.cjs", From 98515a009d01df227c7fbb988b53f63e3bbbe84c Mon Sep 17 00:00:00 2001 From: Simon Dosch Date: Mon, 15 Jul 2024 10:28:32 +0200 Subject: [PATCH 51/92] generate interfaces before foundry tests --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f981c47f..bc31abf8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,5 +47,5 @@ jobs: id: build - name: Run Forge tests - run: if test -d test/foundry && find test/foundry -name '*.sol' | grep -q .; then FOUNDRY_PROFILE=0_8_4 forge test -vvv; else echo "No .sol files found in test/foundry directory. Skipping Forge tests."; fi + run: if test -d test/foundry && find test/foundry -name '*.sol' | grep -q .; then scripts/helpers/generateInterfaces.sh && FOUNDRY_PROFILE=0_8_4 forge test -vvv; else echo "No .sol files found in test/foundry directory. Skipping Forge tests."; fi id: test From 4a5dde1b4962064b26f03f361cfad1d1efa1e978 Mon Sep 17 00:00:00 2001 From: Simon Dosch Date: Mon, 15 Jul 2024 10:52:09 +0200 Subject: [PATCH 52/92] fix interface generation script --- scripts/helpers/generateInterfaces.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/helpers/generateInterfaces.sh b/scripts/helpers/generateInterfaces.sh index 1396a40e..41dcc6c8 100755 --- a/scripts/helpers/generateInterfaces.sh +++ b/scripts/helpers/generateInterfaces.sh @@ -8,7 +8,7 @@ create_interface () { #forge build -mkdir -p interfaces +mkdir -p scripts/helpers/interfaces find out -type f -print0 | while read -d $'\0' file do From 8759b4f151f33fa2d5bd36db06a3ca2ebd84dd0c Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Mon, 15 Jul 2024 11:52:38 +0200 Subject: [PATCH 53/92] wip: deployer --- scripts/deployers/UpgradeStakeManager.s.sol | 67 +++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 scripts/deployers/UpgradeStakeManager.s.sol diff --git a/scripts/deployers/UpgradeStakeManager.s.sol b/scripts/deployers/UpgradeStakeManager.s.sol new file mode 100644 index 00000000..f5e8ad57 --- /dev/null +++ b/scripts/deployers/UpgradeStakeManager.s.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {Script, stdJson, console2 as console} from "forge-std/Script.sol"; + +//cast interface path/to/artifact/file.json +// import { +// ProxyAdmin, +// TransparentUpgradeableProxy, +// ITransparentUpgradeableProxy +// } from "openzeppelin-contracts/contracts/proxy/transparent/ProxyAdmin.sol"; + +import { StakeManager } from "../helpers/interfaces/StakeManager.generated.sol"; +import { StakeManagerProxy } from "../helpers/interfaces/StakeManagerProxy.generated.sol"; +import { ValidatorShare } from "../helpers/interfaces/ValidatorShare.generated.sol"; +import { Registry } from "../helpers/interfaces/Registry.generated.sol"; + +contract UpgradeStakeManager is Script { + using stdJson for string; + + function run() public { + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + + string memory input = vm.readFile("scripts/deployers/input.json"); + string memory chainIdSlug = string(abi.encodePacked('["', vm.toString(block.chainid), '"]')); + address emProxyAddress = input.readAddress(string.concat(chainIdSlug, ".emissionManagerProxy")); + address emProxyAdmin = input.readAddress(string.concat(chainIdSlug, ".emProxyAdmin")); + address newTreasury = input.readAddress(string.concat(chainIdSlug, ".treasury")); + + vm.startBroadcast(deployerPrivateKey); + + StakeManager stakeManagerImpl; + stakeManagerImpl = StakeManager(deployCode("out/StakeManager.sol/StakeManager.json")); + + console.log("deployed StakeManager Implementation at: ", address(stakeManagerImpl)); + + ValidatorShare validatorShareImpl; + validatorShareImpl = ValidatorShare(deployCode("out/ValidatorShare.sol/ValidatorShare.json")); + + + console.log("deployed ValidatorShare Implementation at: ", address(validatorShareImpl)); + + vm.stopBroadcast(); + + Registry registry = Registry(0x33a02E6cC863D393d6Bf231B697b82F6e499cA71); + console.log("found Registry at: ", address(registry)); + + StakeManagerProxy stakeManagerProxy = StakeManagerProxy(0x5e3Ef299fDDf15eAa0432E6e66473ace8c13D908); + console.log("found StakeManagerProxy at: ", address(stakeManagerProxy)); + + + + // set registry valshare value + // set proxy impl + // call initLegacy + + // bytes memory payloadReg = abi.encodeWithSelector( + // ProxyAdmin.upgradeAndCall.selector, + // ITransparentUpgradeableProxy(address(emProxy)), + // address(newEmImpl), + // abi.encodeWithSelector(DefaultEmissionManager.reinitialize.selector) + // ); + + // console.log("Send this payload to: ", emProxyAdmin); + // console.logBytes(payload); + } +} \ No newline at end of file From f5cd0a600e72bd298b3fdc7070b70ec8879a3d22 Mon Sep 17 00:00:00 2001 From: Simon Dosch Date: Mon, 15 Jul 2024 13:24:41 +0200 Subject: [PATCH 54/92] update foundry config --- .github/workflows/ci.yml | 4 ++-- foundry.toml | 29 +++++++++++++++-------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bc31abf8..e8c4394b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,9 +43,9 @@ jobs: - name: Run Forge build run: | forge --version - forge build --sizes --skip test + forge build --sizes id: build - name: Run Forge tests - run: if test -d test/foundry && find test/foundry -name '*.sol' | grep -q .; then scripts/helpers/generateInterfaces.sh && FOUNDRY_PROFILE=0_8_4 forge test -vvv; else echo "No .sol files found in test/foundry directory. Skipping Forge tests."; fi + run: if test -d test/foundry && find test/foundry -name '*.sol' | grep -q .; then npm run generate:interfaces && forge test -vvv; else echo "No .sol files found in test/foundry directory. Skipping Forge tests."; fi id: test diff --git a/foundry.toml b/foundry.toml index f9674221..8dabbfcd 100644 --- a/foundry.toml +++ b/foundry.toml @@ -1,24 +1,25 @@ [profile.default] src = 'contracts' out = 'out' -libs = ['node_modules'] -no-match-path = 'test/foundry' +libs = ['node_modules', 'lib'] +no-match-contract = 'StakeManagerTestable' optimizer = true optimizer_runs = 200 via_ir = true cache_path = 'forge-cache' verbosity = 2 -solc_version = '0.5.17' +# solc_version = '0.5.17' ffi = true remappings = [ "openzeppelin-solidity/=node_modules/openzeppelin-solidity/", - "solidity-rlp/=node_modules/solidity-rlp/" + "solidity-rlp/=node_modules/solidity-rlp/", + "@ensdomains/=node_modules/@ensdomains/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "forge-std/=lib/forge-std/src/", + "hardhat/=node_modules/hardhat/" ] - -[profile.0_8_4] -solc_version = '0.8.4' -src = 'test' -libs = ["lib"] +fs_permissions = [{ access = "read", path = "./scripts/"}, { access = "read", path = "./test/"}, { access = "read", path = "./out/"}] +auto_detect_solc = true [invariant] fail_on_revert = false @@ -37,11 +38,11 @@ number_underscore = "thousands" [rpc_endpoints] anvil = "http://127.0.0.1:8545" -mainnet = "https://mainnet.infura.io/v3/${INFURA_KEY}" -goerli = "https://goerli.infura.io/v3/${INFURA_KEY}" -sepolia = "https://sepolia.infura.io/v3/${INFURA_KEY}" -polygon_pos = "https://polygon-mainnet.infura.io/v3/${INFURA_KEY}" -mumbai = "https://polygon-mumbai.infura.io/v3/${INFURA_KEY}" +mainnet = "https://mainnet.infura.io/v3/${INFURA_TOKEN}" +goerli = "https://goerli.infura.io/v3/${INFURA_TOKEN}" +sepolia = "https://sepolia.infura.io/v3/${INFURA_TOKEN}" +polygon_pos = "https://polygon-mainnet.infura.io/v3/${INFURA_TOKEN}" +mumbai = "https://polygon-mumbai.infura.io/v3/${INFURA_TOKEN}" polygon_zkevm = "https://zkevm-rpc.com" polygon_zkevm_testnet = "https://rpc.public.zkevm-test.net" From a5fd7d69363d44fe6ed6c41d8445b43dca43b21d Mon Sep 17 00:00:00 2001 From: Simon Dosch Date: Mon, 15 Jul 2024 13:26:16 +0200 Subject: [PATCH 55/92] add UpgradeStakeManager_Sepolia script --- .gitignore | 1 + package.json | 9 ++- scripts/deployers/CounterDeployer.s.sol | 43 ----------- .../UpgradeStakeManager_Sepolia.s.sol | 77 +++++++++++++++++++ scripts/deployers/pol-upgrade/input.json | 18 +++++ 5 files changed, 101 insertions(+), 47 deletions(-) delete mode 100644 scripts/deployers/CounterDeployer.s.sol create mode 100644 scripts/deployers/pol-upgrade/UpgradeStakeManager_Sepolia.s.sol create mode 100644 scripts/deployers/pol-upgrade/input.json diff --git a/.gitignore b/.gitignore index 96b59fac..9ff034ca 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ contractAddresses.json # ignore generated files +broadcast/*/*/dry-run contracts/root/predicates/TransferWithSigUtils.sol contracts/common/mixin/ChainIdMixin.sol test/helpers/marketplaceUtils.js diff --git a/package.json b/package.json index 35dd8b64..cdd829ac 100644 --- a/package.json +++ b/package.json @@ -9,17 +9,18 @@ "test": "test" }, "scripts": { - "build": "forge build --skip test", + "build": "forge build", "test:hardhat": "npx hardhat test", - "generate-interfaces": "scripts/helpers/generateInterfaces.sh", - "test:foundry": "FOUNDRY_PROFILE=0_8_4 forge test", + "generate:interfaces": "scripts/helpers/generateInterfaces.sh", + "test:foundry": "forge test", "test:ci": "scripts/run-test.sh", "testrpc": "ganache --chain.hardfork istanbul --wallet.mnemonic 'clock radar mass judge dismiss just intact mind resemble fringe diary casino' -p 8545 --gasLimit 10000000 --gasPrice 0 --chain.allowUnlimitedContractSize --accounts 200", "template:process": "node scripts/process-templates.cjs", "coverage": "LOCAL_NETWORK=true npx hardhat coverage --solcoverjs .solcover.cjs", "bor:simulate": "cd test-bor-docker && bash run-docker.sh", "bor:stop": "cd test-bor-docker && bash stop-docker.sh", - "bor:clean": "cd test-bor-docker && bash clean.sh" + "bor:clean": "cd test-bor-docker && bash clean.sh", + "upgrade:stakeManager:sepolia": "forge script scripts/deployers/pol-upgrade/UpgradeStakeManager_Sepolia.s.sol --rpc-url sepolia" }, "keywords": [], "author": "Jaynti Kanani , Simon Dosch Date: Mon, 15 Jul 2024 18:47:50 +0200 Subject: [PATCH 56/92] feat: upgradeStakeManager script --- .../UpgradeStakeManager_Sepolia.s.sol | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/scripts/deployers/pol-upgrade/UpgradeStakeManager_Sepolia.s.sol b/scripts/deployers/pol-upgrade/UpgradeStakeManager_Sepolia.s.sol index 26a05b49..3978d4ba 100644 --- a/scripts/deployers/pol-upgrade/UpgradeStakeManager_Sepolia.s.sol +++ b/scripts/deployers/pol-upgrade/UpgradeStakeManager_Sepolia.s.sol @@ -8,9 +8,8 @@ import { StakeManagerProxy } from "../../helpers/interfaces/StakeManagerProxy.ge import { ValidatorShare } from "../../helpers/interfaces/ValidatorShare.generated.sol"; import { Registry } from "../../helpers/interfaces/Registry.generated.sol"; import { Governance } from "../../helpers/interfaces/Governance.generated.sol"; -import { ERC20 } from "../../helpers/interfaces/ERC20.generated.sol"; -contract UpgradeEmissionManager is Script { +contract UpgradeStakeManager_Sepolia is Script { using stdJson for string; function run() public { @@ -62,16 +61,24 @@ contract UpgradeEmissionManager is Script { console.logBytes(payloadRegistry); bytes memory payloadStakeManager = abi.encodeWithSelector( - stakeManagerProxy.updateAndCall.selector, - address(stakeManagerImpl), + stakeManagerProxy.updateImplementation.selector, + address(stakeManagerImpl) + ); + + console.log("Send payloadStakeManager to: ", address(stakeManagerProxy)); + console.logBytes(payloadStakeManager); + + bytes memory payloadInitializePol = abi.encodeWithSelector( + governance.update.selector, + address(stakeManagerProxy), abi.encodeWithSelector( stakeManager.initializePOL.selector, address(polToken), migration ) ); - - console.log("Send payloadStakeManager to: ", address(stakeManagerProxy)); - console.logBytes(payloadStakeManager); + + console.log("Send payloadInitializePol to: ", address(governance)); + console.logBytes(payloadInitializePol); } } From 855f45ec8dde0c91fbcf8a670de0057463157559 Mon Sep 17 00:00:00 2001 From: Simon Dosch Date: Mon, 15 Jul 2024 18:48:39 +0200 Subject: [PATCH 57/92] version 0.4.0 --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index cdd829ac..7c1223c3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "matic-protocol", "description": "New repo using Hardhat and Foundry", - "version": "0.3.2", + "version": "0.4.0", "main": "hardhat.config.cjs", "type": "module", "directories": { @@ -20,7 +20,8 @@ "bor:simulate": "cd test-bor-docker && bash run-docker.sh", "bor:stop": "cd test-bor-docker && bash stop-docker.sh", "bor:clean": "cd test-bor-docker && bash clean.sh", - "upgrade:stakeManager:sepolia": "forge script scripts/deployers/pol-upgrade/UpgradeStakeManager_Sepolia.s.sol --rpc-url sepolia" + "upgrade:stakeManager:sepolia": "forge script scripts/deployers/pol-upgrade/UpgradeStakeManager_Sepolia.s.sol --rpc-url sepolia", + "upgrade:depositManager:sepolia": "forge script scripts/deployers/pol-upgrade/UpgradeDepositManager_Sepolia.s.sol --rpc-url sepolia" }, "keywords": [], "author": "Jaynti Kanani , Simon Dosch Date: Mon, 15 Jul 2024 18:49:11 +0200 Subject: [PATCH 58/92] feat: upgradeDepositManager script (plasma bridge) --- scripts/deployers/UpgradeStakeManager.s.sol | 67 ------------ .../UpgradeDepositManager_Sepolia.s.sol | 102 ++++++++++++++++++ scripts/deployers/pol-upgrade/input.json | 5 +- 3 files changed, 106 insertions(+), 68 deletions(-) delete mode 100644 scripts/deployers/UpgradeStakeManager.s.sol create mode 100644 scripts/deployers/pol-upgrade/UpgradeDepositManager_Sepolia.s.sol diff --git a/scripts/deployers/UpgradeStakeManager.s.sol b/scripts/deployers/UpgradeStakeManager.s.sol deleted file mode 100644 index f5e8ad57..00000000 --- a/scripts/deployers/UpgradeStakeManager.s.sol +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {Script, stdJson, console2 as console} from "forge-std/Script.sol"; - -//cast interface path/to/artifact/file.json -// import { -// ProxyAdmin, -// TransparentUpgradeableProxy, -// ITransparentUpgradeableProxy -// } from "openzeppelin-contracts/contracts/proxy/transparent/ProxyAdmin.sol"; - -import { StakeManager } from "../helpers/interfaces/StakeManager.generated.sol"; -import { StakeManagerProxy } from "../helpers/interfaces/StakeManagerProxy.generated.sol"; -import { ValidatorShare } from "../helpers/interfaces/ValidatorShare.generated.sol"; -import { Registry } from "../helpers/interfaces/Registry.generated.sol"; - -contract UpgradeStakeManager is Script { - using stdJson for string; - - function run() public { - uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); - - string memory input = vm.readFile("scripts/deployers/input.json"); - string memory chainIdSlug = string(abi.encodePacked('["', vm.toString(block.chainid), '"]')); - address emProxyAddress = input.readAddress(string.concat(chainIdSlug, ".emissionManagerProxy")); - address emProxyAdmin = input.readAddress(string.concat(chainIdSlug, ".emProxyAdmin")); - address newTreasury = input.readAddress(string.concat(chainIdSlug, ".treasury")); - - vm.startBroadcast(deployerPrivateKey); - - StakeManager stakeManagerImpl; - stakeManagerImpl = StakeManager(deployCode("out/StakeManager.sol/StakeManager.json")); - - console.log("deployed StakeManager Implementation at: ", address(stakeManagerImpl)); - - ValidatorShare validatorShareImpl; - validatorShareImpl = ValidatorShare(deployCode("out/ValidatorShare.sol/ValidatorShare.json")); - - - console.log("deployed ValidatorShare Implementation at: ", address(validatorShareImpl)); - - vm.stopBroadcast(); - - Registry registry = Registry(0x33a02E6cC863D393d6Bf231B697b82F6e499cA71); - console.log("found Registry at: ", address(registry)); - - StakeManagerProxy stakeManagerProxy = StakeManagerProxy(0x5e3Ef299fDDf15eAa0432E6e66473ace8c13D908); - console.log("found StakeManagerProxy at: ", address(stakeManagerProxy)); - - - - // set registry valshare value - // set proxy impl - // call initLegacy - - // bytes memory payloadReg = abi.encodeWithSelector( - // ProxyAdmin.upgradeAndCall.selector, - // ITransparentUpgradeableProxy(address(emProxy)), - // address(newEmImpl), - // abi.encodeWithSelector(DefaultEmissionManager.reinitialize.selector) - // ); - - // console.log("Send this payload to: ", emProxyAdmin); - // console.logBytes(payload); - } -} \ No newline at end of file diff --git a/scripts/deployers/pol-upgrade/UpgradeDepositManager_Sepolia.s.sol b/scripts/deployers/pol-upgrade/UpgradeDepositManager_Sepolia.s.sol new file mode 100644 index 00000000..e7139f25 --- /dev/null +++ b/scripts/deployers/pol-upgrade/UpgradeDepositManager_Sepolia.s.sol @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {Script, stdJson, console2 as console} from "forge-std/Script.sol"; + +import {Registry} from "../../helpers/interfaces/Registry.generated.sol"; +import {Governance} from "../../helpers/interfaces/Governance.generated.sol"; +import {DepositManager} from "../../helpers/interfaces/DepositManager.generated.sol"; +import {DepositManagerProxy} from "../../helpers/interfaces/DepositManagerProxy.generated.sol"; +import { ERC20 } from "../../helpers/interfaces/ERC20.generated.sol"; + +contract UpgradeDepositManager_Sepolia is Script { + using stdJson for string; + + function run() public { + uint256 deployerPrivateKey = vm.promptSecretUint("Enter deployer private key: "); + + string memory input = vm.readFile("scripts/deployers/pol-upgrade/input.json"); + string memory chainIdSlug = string(abi.encodePacked('["', vm.toString(block.chainid), '"]')); + address governanceAddress = input.readAddress(string.concat(chainIdSlug, ".governance")); + address matic = input.readAddress(string.concat(chainIdSlug, ".matic")); + address polToken = input.readAddress(string.concat(chainIdSlug, ".polToken")); + address migration = input.readAddress(string.concat(chainIdSlug, ".migration")); + address registryAddress = input.readAddress(string.concat(chainIdSlug, ".registry")); + address payable depositManagerProxyAddress = payable(input.readAddress(string.concat(chainIdSlug, ".depositManagerProxy"))); + address nativeGasTokenAddress = address(0x0000000000000000000000000000000000001010); + + Registry registry = Registry(registryAddress); + Governance governance = Governance(governanceAddress); + + // STEP 1 + // Call updateContractMap on registry to add “matic”, “pol” and “polygonMigration” + + // pol + bytes memory payloadContractMapPol = abi.encodeWithSelector( + governance.update.selector, registryAddress, abi.encodeWithSelector(registry.updateContractMap.selector, keccak256("pol"), polToken) + ); + + console.log("Send payloadContractMapPol to: ", governanceAddress); + console.logBytes(payloadContractMapPol); + + // matic + bytes memory payloadContractMapMatic = abi.encodeWithSelector( + governance.update.selector, registryAddress, abi.encodeWithSelector(registry.updateContractMap.selector, keccak256("matic"), matic) + ); + + console.log("\n Send payloadContractMapMatic to: ", governanceAddress); + console.logBytes(payloadContractMapMatic); + + // polygonMigration + bytes memory payloadContractMapMigration = abi.encodeWithSelector( + governance.update.selector, registryAddress, abi.encodeWithSelector(registry.updateContractMap.selector, keccak256("polygonMigration"), migration) + ); + + console.log("\n Send payloadContractMapMigration to: ", governanceAddress); + console.logBytes(payloadContractMapMigration); + + // STEP 2 + // call mapToken on the Registry to map POL to the PoS native gas token address (1010) + + bytes memory payloadMapToken = abi.encodeWithSelector( + governance.update.selector, registryAddress, abi.encodeWithSelector(registry.mapToken.selector, polToken, nativeGasTokenAddress, false) + ); + + console.log("\n Send payloadMapToken to: ", governanceAddress); + console.logBytes(payloadMapToken); + + // STEP 3 + // deploy new DepositManager version and update proxy + + // deploy impl + vm.startBroadcast(deployerPrivateKey); + + DepositManager depositManagerImpl; + depositManagerImpl = DepositManager(payable(deployCode("out/DepositManager.sol/DepositManager.json"))); + + vm.stopBroadcast(); + + DepositManager depositManager = DepositManager(depositManagerProxyAddress); + DepositManagerProxy depositManagerProxy = DepositManagerProxy(depositManagerProxyAddress); + + // update proxy + bytes memory payloadUpgradeDepositManager = abi.encodeWithSelector( + depositManagerProxy.updateImplementation.selector, + address(depositManagerImpl) + ); + + console.log("\n Send payloadUpgradeDepositManager to: ", address(depositManagerProxy)); + console.logBytes(payloadUpgradeDepositManager); + + // STEP 4 + // call migrateMatic on the new DepositManager, migrating all MATIC + ERC20 maticToken = ERC20(matic); + uint256 amount = maticToken.balanceOf(address(depositManagerProxy)); + bytes memory payloadMigrateMatic = abi.encodeWithSelector( + governance.update.selector, registryAddress, abi.encodeWithSelector(depositManager.migrateMatic.selector, amount) + ); + + console.log("\n Send payloadMigrateMatic to: ", address(depositManagerProxy)); + console.logBytes(payloadMigrateMatic); + } +} diff --git a/scripts/deployers/pol-upgrade/input.json b/scripts/deployers/pol-upgrade/input.json index bb77d56e..6d26e826 100644 --- a/scripts/deployers/pol-upgrade/input.json +++ b/scripts/deployers/pol-upgrade/input.json @@ -2,6 +2,7 @@ "1": { "registry": "0x33a02E6cC863D393d6Bf231B697b82F6e499cA71", "stakeManagerProxy": "0x5e3Ef299fDDf15eAa0432E6e66473ace8c13D908", + "depositManagerProxy": "0x401F6c983eA34274ec46f84D70b31C151321188b", "governance": "0x6e7a5820baD6cebA8Ef5ea69c0C92EbbDAc9CE48", "timelock": "0xCaf0aa768A3AE1297DF20072419Db8Bb8b5C8cEf", "polToken": "0x455e53CBB86018Ac2B8092FdCd39d8444aFFC3F6", @@ -10,9 +11,11 @@ "11155111": { "registry": "0xfE92F7c3a701e43d8479738c8844bCc555b9e5CD", "stakeManagerProxy": "0x4ae8f648b1ec892b6cc68c89cc088583964d08be", + "depositManagerProxy": "0x44Ad17990F9128C6d823Ee10dB7F0A5d40a731A4", "timelock": "onlyMainnet", "governance": "0xB7086eda3180c728C1536B35c4d54F6A2B33D6aC", "polToken": "0x44499312f493F62f2DFd3C6435Ca3603EbFCeeBa", + "matic": "0x3fd0A53F4Bf853985a95F4Eb3F9C9FDE1F8e2b53", "migration": "0x3A3B750E7d4d389Bc1d0be20E5D09530F82B9911" } -} +} \ No newline at end of file From c4dedd311d8ac9cbc6fb7f6983e7377fc1e57678 Mon Sep 17 00:00:00 2001 From: Simon Dosch Date: Mon, 15 Jul 2024 18:49:39 +0200 Subject: [PATCH 59/92] deploy: upgrade impls on sepolia --- .../11155111/run-1721057237.json | 62 ++++++++++ .../11155111/run-latest.json | 62 ++++++++++ .../11155111/run-1721057742.json | 112 ++++++++++++++++++ .../11155111/run-latest.json | 112 ++++++++++++++++++ 4 files changed, 348 insertions(+) create mode 100644 broadcast/UpgradeDepositManager_Sepolia.s.sol/11155111/run-1721057237.json create mode 100644 broadcast/UpgradeDepositManager_Sepolia.s.sol/11155111/run-latest.json create mode 100644 broadcast/UpgradeStakeManager_Sepolia.s.sol/11155111/run-1721057742.json create mode 100644 broadcast/UpgradeStakeManager_Sepolia.s.sol/11155111/run-latest.json diff --git a/broadcast/UpgradeDepositManager_Sepolia.s.sol/11155111/run-1721057237.json b/broadcast/UpgradeDepositManager_Sepolia.s.sol/11155111/run-1721057237.json new file mode 100644 index 00000000..b0c4eb8b --- /dev/null +++ b/broadcast/UpgradeDepositManager_Sepolia.s.sol/11155111/run-1721057237.json @@ -0,0 +1,62 @@ +{ + "transactions": [ + { + "hash": "0x7791e1d6b77d0b8483bc9294d1562089b2257f9e478014154dc9dc6e70ca7afc", + "transactionType": "CREATE", + "contractName": null, + "contractAddress": "0x332d42a3c83fbc46f27137278018a589c637ce3b", + "function": null, + "arguments": null, + "transaction": { + "from": "0x0724d72eb61e508d81ca701881f2248f092953bf", + "gas": "0x23dd76", + "value": "0x0", + "input": "0x608060405268056bc75e2d6310000060085534801561001d57600080fd5b50600080546001600160a01b031916331780825560405182916001600160a01b03169082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600280546001600160a01b0319166001600160a01b039290921691909117905550611ed9806100976000396000f3fe6080604052600436106101815760003560e01c80638f32d59b116100d1578063cb10f94c1161008a578063e7af7ba111610064578063e7af7ba11461063c578063f220371114610663578063f2fde38b14610696578063f83d08ba146106c957610181565b8063cb10f94c146105d9578063cf309012146105ee578063d29a4bf61461060357610181565b80638f32d59b1461050a57806397feb92614610533578063987ab9db1461056c57806398ea5fca14610181578063a69df4b514610581578063b02c43d01461059657610181565b80635aa6e6751161013e5780637b103999116101185780637b103999146103c55780637b1f7117146103da5780638b9e4f93146104b25780638da5cb5b146104f557610181565b80635aa6e675146103715780636567082814610386578063715018a6146103b057610181565b8063072b15351461018b578063150b7a02146101ce57806342be8379146102be57806342fc47fb146102d357806349f4cc17146103045780634b56c07114610347575b6101896106de565b005b34801561019757600080fd5b50610189600480360360608110156101ae57600080fd5b506001600160a01b038135811691602081013590911690604001356107c0565b3480156101da57600080fd5b506102a1600480360360808110156101f157600080fd5b6001600160a01b0382358116926020810135909116916040820135919081019060808101606082013564010000000081111561022c57600080fd5b82018360208201111561023e57600080fd5b8035906020019184600183028401116401000000008311171561026057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610892945050505050565b604080516001600160e01b03199092168252519081900360200190f35b3480156102ca57600080fd5b506101896108a2565b3480156102df57600080fd5b506102e86109b3565b604080516001600160a01b039092168252519081900360200190f35b34801561031057600080fd5b506101896004803603606081101561032757600080fd5b506001600160a01b038135811691602081013590911690604001356109c2565b34801561035357600080fd5b506101896004803603602081101561036a57600080fd5b5035610f42565b34801561037d57600080fd5b506102e8610f88565b34801561039257600080fd5b50610189600480360360208110156103a957600080fd5b5035610f97565b3480156103bc57600080fd5b50610189610fab565b3480156103d157600080fd5b506102e8611006565b3480156103e657600080fd5b50610189600480360360608110156103fd57600080fd5b81019060208101813564010000000081111561041857600080fd5b82018360208201111561042a57600080fd5b8035906020019184602083028401116401000000008311171561044c57600080fd5b91939092909160208101903564010000000081111561046a57600080fd5b82018360208201111561047c57600080fd5b8035906020019184602083028401116401000000008311171561049e57600080fd5b9193509150356001600160a01b0316611015565b3480156104be57600080fd5b50610189600480360360608110156104d557600080fd5b506001600160a01b0381358116916020810135909116906040013561127f565b34801561050157600080fd5b506102e86112f1565b34801561051657600080fd5b5061051f611300565b604080519115158252519081900360200190f35b34801561053f57600080fd5b506101896004803603604081101561055657600080fd5b506001600160a01b038135169060200135611311565b34801561057857600080fd5b506102e861131c565b34801561058d57600080fd5b5061018961132b565b3480156105a257600080fd5b506105c0600480360360208110156105b957600080fd5b503561133d565b6040805192835260208301919091528051918290030190f35b3480156105e557600080fd5b506102e8611356565b3480156105fa57600080fd5b5061051f611365565b34801561060f57600080fd5b506101896004803603604081101561062657600080fd5b506001600160a01b038135169060200135611375565b34801561064857600080fd5b50610651611380565b60408051918252519081900360200190f35b34801561066f57600080fd5b506101896004803603602081101561068657600080fd5b50356001600160a01b0316611386565b3480156106a257600080fd5b50610189600480360360208110156106b957600080fd5b50356001600160a01b03166113b9565b3480156106d557600080fd5b506101896113d3565b60035460408051638b9c948960e01b815290516000926001600160a01b031691638b9c9489916004808301926020929190829003018186803b15801561072357600080fd5b505afa158015610737573d6000803e3d6000fd5b505050506040513d602081101561074d57600080fd5b505160408051630d0e30db60e41b8152905191925082916001600160a01b0383169163d0e30db091349160048082019260009290919082900301818588803b15801561079857600080fd5b505af11580156107ac573d6000803e3d6000fd5b50505050506107bc3383346113e3565b5050565b600354604080516301f07db560e01b81526001600160a01b038681166004830152915191909216916301f07db5916024808301926020929190829003018186803b15801561080d57600080fd5b505afa158015610821573d6000803e3d6000fd5b505050506040513d602081101561083757600080fd5b5051610877576040805162461bcd60e51b815260206004820152600a6024820152696e6f742065726337323160b01b604482015290519081900360640190fd5b610882338483611541565b61088d8284836113e3565b505050565b630a85bd0160e11b949350505050565b60035460408051630c91702f60e31b8152815160009384936001600160a01b039091169263648b81789260048083019392829003018186803b1580156108e757600080fd5b505afa1580156108fb573d6000803e3d6000fd5b505050506040513d604081101561091157600080fd5b50805160209091015160055491935091506001600160a01b03808316911614158061094a57506007546001600160a01b03838116911614155b6109855760405162461bcd60e51b815260040180806020018281038252603e815260200180611e41603e913960400191505060405180910390fd5b600780546001600160a01b039384166001600160a01b03199182161790915560058054929093169116179055565b6007546001600160a01b031681565b600354604080516337b1d58560e01b815233600482015290516001600160a01b03909216916337b1d58591602480820192602092909190829003018186803b158015610a0d57600080fd5b505afa158015610a21573d6000803e3d6000fd5b505050506040513d6020811015610a3757600080fd5b50516003811115610a4457fe5b60ff16610a90576040805162461bcd60e51b81526020600482015260156024820152744e6f7420612076616c69642070726564696361746560581b604482015290519081900360640190fd5b60035460408051638b9c948960e01b815290516000926001600160a01b031691638b9c9489916004808301926020929190829003018186803b158015610ad557600080fd5b505afa158015610ae9573d6000803e3d6000fd5b505050506040513d6020811015610aff57600080fd5b5051600354604080516336a8279560e21b81526001600160a01b038881166004830152915193945091169163daa09e5491602480820192602092909190829003018186803b158015610b5057600080fd5b505afa158015610b64573d6000803e3d6000fd5b505050506040513d6020811015610b7a57600080fd5b505115610bf657604080516323b872dd60e01b81523060048201526001600160a01b038581166024830152604482018590529151918616916323b872dd9160648082019260009290919082900301818387803b158015610bd957600080fd5b505af1158015610bed573d6000803e3d6000fd5b50505050610f3c565b806001600160a01b0316846001600160a01b03161415610c7e5760408051627b8a6760e11b8152600481018490526001600160a01b0385811660248301529151869283169162f714ce91604480830192600092919082900301818387803b158015610c6057600080fd5b505af1158015610c74573d6000803e3d6000fd5b5050505050610f3c565b60035460408051646d6174696360d81b8152815190819003600501812063cac39a0560e01b8252600482015290516001600160a01b039092169163cac39a0591602480820192602092909190829003018186803b158015610cde57600080fd5b505afa158015610cf2573d6000803e3d6000fd5b505050506040513d6020811015610d0857600080fd5b50516001600160a01b0385811691161415610e6d576003805460408051621c1bdb60ea1b8152815190819003909301832063cac39a0560e01b84526004840152516001600160a01b039091169163cac39a05916024808301926020929190829003018186803b158015610d7a57600080fd5b505afa158015610d8e573d6000803e3d6000fd5b505050506040513d6020811015610da457600080fd5b50516040805163a9059cbb60e01b81526001600160a01b038681166004830152602482018690529151919092169163a9059cbb9160448083019260209291908290030181600087803b158015610df957600080fd5b505af1158015610e0d573d6000803e3d6000fd5b505050506040513d6020811015610e2357600080fd5b5051610e68576040805162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b604482015290519081900360640190fd5b610f3c565b836001600160a01b031663a9059cbb84846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015610ecd57600080fd5b505af1158015610ee1573d6000803e3d6000fd5b505050506040513d6020811015610ef757600080fd5b5051610f3c576040805162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b604482015290519081900360640190fd5b50505050565b610f4a6115b6565b80610f5457600080fd5b6008546040518291907f010c0265813c273963aa5e8683cf5c45a3b744ba6369c22af0958ec5fcf16b2090600090a3600855565b6002546001600160a01b031681565b610f9f6115b6565b610fa8816115ff565b50565b610fb3611300565b610fbc57600080fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6003546001600160a01b031681565b61101d6118b0565b838214611061576040805162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a5908125b9c1d5d609a1b604482015290519081900360640190fd5b6004805460408051635391f48360e01b8152928301879052516000926001600160a01b0390921691635391f48391602480830192602092919082900301818787803b1580156110af57600080fd5b505af11580156110c3573d6000803e3d6000fd5b505050506040513d60208110156110d957600080fd5b50516003549091506001600160a01b031660005b8681101561127557816001600160a01b03166301f07db589898481811061111057fe5b905060200201356001600160a01b03166040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561116657600080fd5b505afa15801561117a573d6000803e3d6000fd5b505050506040513d602081101561119057600080fd5b5051156111d4576111cf338989848181106111a757fe5b905060200201356001600160a01b03168888858181106111c357fe5b90506020020135611541565b611221565b61122133308888858181106111e557fe5b905060200201358b8b868181106111f857fe5b905060200201356001600160a01b03166001600160a01b03166118f8909392919063ffffffff16565b61125a8489898481811061123157fe5b905060200201356001600160a01b031688888581811061124d57fe5b9050602002013586611952565b61126b83600163ffffffff611c6d16565b92506001016110ed565b5050505050505050565b6008548111156112d6576040805162461bcd60e51b815260206004820152601d60248201527f657863656564206d6178696d756d206465706f73697420616d6f756e74000000604482015290519081900360640190fd5b6108826001600160a01b03841633308463ffffffff6118f816565b6000546001600160a01b031690565b6000546001600160a01b0316331490565b6107bc82338361127f565b6004546001600160a01b031681565b6113336115b6565b61133b611c86565b565b6006602052600090815260409020805460019091015482565b6005546001600160a01b031681565b600154600160a01b900460ff1681565b6107bc8233836107c0565b60085481565b61138e611300565b61139757600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6113c1611300565b6113ca57600080fd5b610fa881611c95565b6113db6115b6565b61133b611d03565b6113eb6118b0565b60035460408051636416c18360e01b81526001600160a01b038086166004830152915185939290921691636416c18391602480820192602092909190829003018186803b15801561143b57600080fd5b505afa15801561144f573d6000803e3d6000fd5b505050506040513d602081101561146557600080fd5b50516114ae576040805162461bcd60e51b81526020600482015260136024820152721513d2d15397d393d517d4d5541413d4951151606a1b604482015290519081900360640190fd5b610f3c848484600460009054906101000a90046001600160a01b03166001600160a01b0316635391f48360016040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b15801561151057600080fd5b505af1158015611524573d6000803e3d6000fd5b505050506040513d602081101561153a57600080fd5b5051611952565b60408051632142170760e11b81526001600160a01b038581166004830152306024830152604482018490529151918416916342842e0e9160648082019260009290919082900301818387803b15801561159957600080fd5b505af11580156115ad573d6000803e3d6000fd5b50505050505050565b6002546001600160a01b0316331461133b5760405162461bcd60e51b8152600401808060200182810382526026815260200180611e7f6026913960400191505060405180910390fd5b60035460408051646d6174696360d81b8152815190819003600501812063cac39a0560e01b8252600482015290516000926001600160a01b03169163cac39a05916024808301926020929190829003018186803b15801561165f57600080fd5b505afa158015611673573d6000803e3d6000fd5b505050506040513d602081101561168957600080fd5b5051600354604080516f3837b63cb3b7b726b4b3b930ba34b7b760811b8152815190819003601001812063cac39a0560e01b8252600482015290519293506000926001600160a01b039092169163cac39a0591602480820192602092909190829003018186803b1580156116fc57600080fd5b505afa158015611710573d6000803e3d6000fd5b505050506040513d602081101561172657600080fd5b5051604080516370a0823160e01b8152306004820152905191925084916001600160a01b038516916370a08231916024808301926020929190829003018186803b15801561177357600080fd5b505afa158015611787573d6000803e3d6000fd5b505050506040513d602081101561179d57600080fd5b505110156117dc5760405162461bcd60e51b815260040180806020018281038252602c815260200180611e15602c913960400191505060405180910390fd5b816001600160a01b031663095ea7b382856040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b505050506040513d602081101561186657600080fd5b5050604080516308a960c160e31b81526004810185905290516001600160a01b0383169163454b060891602480830192600092919082900301818387803b15801561159957600080fd5b600154600160a01b900460ff161561133b576040805162461bcd60e51b81526020600482015260066024820152651b1bd8dad95960d21b604482015290519081900360640190fd5b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052610f3c908590611d18565b60035460408051646d6174696360d81b8152815190819003600501812063cac39a0560e01b8252600482015290516000926001600160a01b03169163cac39a05916024808301926020929190829003018186803b1580156119b257600080fd5b505afa1580156119c6573d6000803e3d6000fd5b505050506040513d60208110156119dc57600080fd5b505190506001600160a01b038481169082161415611a02576119fd836115ff565b611aa2565b6003805460408051621c1bdb60ea1b8152815190819003909301832063cac39a0560e01b84526004840152516001600160a01b039091169163cac39a05916024808301926020929190829003018186803b158015611a5f57600080fd5b505afa158015611a73573d6000803e3d6000fd5b505050506040513d6020811015611a8957600080fd5b50516001600160a01b0385811691161415611aa2578093505b604080518082018252606087811b6bffffffffffffffffffffffff199081168284015287821b16607483015260888083018790528351808403909101815260a883018452805160209182012083524281840190815260008781526006835285812094518555905160019094019390935560055460075485516001600160a01b03808d1682860152808c16828901529481018a905260808082018a90528751808303909101815260a082018089526316f1983160e01b905291851660a4820181815260c48301988952835160e4840152835196909416976316f198319791969395909361010490930192908601918190849084905b83811015611bae578181015183820152602001611b96565b50505050905090810190601f168015611bdb5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b158015611bfb57600080fd5b505af1158015611c0f573d6000803e3d6000fd5b50505050836001600160a01b0316856001600160a01b03167f1dadc8d0683c6f9824e885935c1bec6f76816730dcec148dda8cf25a7b9f797b8585604051808381526020018281526020019250505060405180910390a35050505050565b600082820183811015611c7f57600080fd5b9392505050565b6001805460ff60a01b19169055565b6001600160a01b038116611ca857600080fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001805460ff60a01b1916600160a01b179055565b611d2a826001600160a01b0316611e0e565b611d3357600080fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310611d715780518252601f199092019160209182019101611d52565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611dd3576040519150601f19603f3d011682016040523d82523d6000602084013e611dd8565b606091505b509150915081611de757600080fd5b805115610f3c57808060200190516020811015611e0357600080fd5b5051610f3c57600080fd5b3b15159056fe616d6f756e742065786365656473207468697320636f6e74726163742773204d415449432062616c616e636541746c65617374206f6e65206f6620737461746553656e646572206f72206368696c64436861696e20616464726573732073686f756c64206368616e67654f6e6c7920676f7665726e616e636520636f6e747261637420697320617574686f72697a6564a265627a7a72315820af90bf4264f58eb743bcfe1f448541fe7693fe6821f29e1b76d985e33a522baa64736f6c63430005110032", + "nonce": "0x8b", + "chainId": "0xaa36a7" + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "status": "0x1", + "cumulativeGasUsed": "0x10b4441", + "logs": [ + { + "address": "0x332d42a3c83fbc46f27137278018a589c637ce3b", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000724d72eb61e508d81ca701881f2248f092953bf" + ], + "data": "0x", + "blockHash": "0x28a89052310fadb5f07811332a8c04d1752870b21e8ef659a712ce0a7c7ba782", + "blockNumber": "0x605ef4", + "transactionHash": "0x7791e1d6b77d0b8483bc9294d1562089b2257f9e478014154dc9dc6e70ca7afc", + "transactionIndex": "0x63", + "logIndex": "0xde", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000004000000800000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000010000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x7791e1d6b77d0b8483bc9294d1562089b2257f9e478014154dc9dc6e70ca7afc", + "transactionIndex": "0x63", + "blockHash": "0x28a89052310fadb5f07811332a8c04d1752870b21e8ef659a712ce0a7c7ba782", + "blockNumber": "0x605ef4", + "gasUsed": "0x1b98a2", + "effectiveGasPrice": "0x2e2fa16bc", + "from": "0x0724d72eb61e508d81ca701881f2248f092953bf", + "to": null, + "contractAddress": "0x332d42a3c83fbc46f27137278018a589c637ce3b" + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1721057237, + "chain": 11155111, + "commit": "a5fd7d69" +} \ No newline at end of file diff --git a/broadcast/UpgradeDepositManager_Sepolia.s.sol/11155111/run-latest.json b/broadcast/UpgradeDepositManager_Sepolia.s.sol/11155111/run-latest.json new file mode 100644 index 00000000..b0c4eb8b --- /dev/null +++ b/broadcast/UpgradeDepositManager_Sepolia.s.sol/11155111/run-latest.json @@ -0,0 +1,62 @@ +{ + "transactions": [ + { + "hash": "0x7791e1d6b77d0b8483bc9294d1562089b2257f9e478014154dc9dc6e70ca7afc", + "transactionType": "CREATE", + "contractName": null, + "contractAddress": "0x332d42a3c83fbc46f27137278018a589c637ce3b", + "function": null, + "arguments": null, + "transaction": { + "from": "0x0724d72eb61e508d81ca701881f2248f092953bf", + "gas": "0x23dd76", + "value": "0x0", + "input": "0x608060405268056bc75e2d6310000060085534801561001d57600080fd5b50600080546001600160a01b031916331780825560405182916001600160a01b03169082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600280546001600160a01b0319166001600160a01b039290921691909117905550611ed9806100976000396000f3fe6080604052600436106101815760003560e01c80638f32d59b116100d1578063cb10f94c1161008a578063e7af7ba111610064578063e7af7ba11461063c578063f220371114610663578063f2fde38b14610696578063f83d08ba146106c957610181565b8063cb10f94c146105d9578063cf309012146105ee578063d29a4bf61461060357610181565b80638f32d59b1461050a57806397feb92614610533578063987ab9db1461056c57806398ea5fca14610181578063a69df4b514610581578063b02c43d01461059657610181565b80635aa6e6751161013e5780637b103999116101185780637b103999146103c55780637b1f7117146103da5780638b9e4f93146104b25780638da5cb5b146104f557610181565b80635aa6e675146103715780636567082814610386578063715018a6146103b057610181565b8063072b15351461018b578063150b7a02146101ce57806342be8379146102be57806342fc47fb146102d357806349f4cc17146103045780634b56c07114610347575b6101896106de565b005b34801561019757600080fd5b50610189600480360360608110156101ae57600080fd5b506001600160a01b038135811691602081013590911690604001356107c0565b3480156101da57600080fd5b506102a1600480360360808110156101f157600080fd5b6001600160a01b0382358116926020810135909116916040820135919081019060808101606082013564010000000081111561022c57600080fd5b82018360208201111561023e57600080fd5b8035906020019184600183028401116401000000008311171561026057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610892945050505050565b604080516001600160e01b03199092168252519081900360200190f35b3480156102ca57600080fd5b506101896108a2565b3480156102df57600080fd5b506102e86109b3565b604080516001600160a01b039092168252519081900360200190f35b34801561031057600080fd5b506101896004803603606081101561032757600080fd5b506001600160a01b038135811691602081013590911690604001356109c2565b34801561035357600080fd5b506101896004803603602081101561036a57600080fd5b5035610f42565b34801561037d57600080fd5b506102e8610f88565b34801561039257600080fd5b50610189600480360360208110156103a957600080fd5b5035610f97565b3480156103bc57600080fd5b50610189610fab565b3480156103d157600080fd5b506102e8611006565b3480156103e657600080fd5b50610189600480360360608110156103fd57600080fd5b81019060208101813564010000000081111561041857600080fd5b82018360208201111561042a57600080fd5b8035906020019184602083028401116401000000008311171561044c57600080fd5b91939092909160208101903564010000000081111561046a57600080fd5b82018360208201111561047c57600080fd5b8035906020019184602083028401116401000000008311171561049e57600080fd5b9193509150356001600160a01b0316611015565b3480156104be57600080fd5b50610189600480360360608110156104d557600080fd5b506001600160a01b0381358116916020810135909116906040013561127f565b34801561050157600080fd5b506102e86112f1565b34801561051657600080fd5b5061051f611300565b604080519115158252519081900360200190f35b34801561053f57600080fd5b506101896004803603604081101561055657600080fd5b506001600160a01b038135169060200135611311565b34801561057857600080fd5b506102e861131c565b34801561058d57600080fd5b5061018961132b565b3480156105a257600080fd5b506105c0600480360360208110156105b957600080fd5b503561133d565b6040805192835260208301919091528051918290030190f35b3480156105e557600080fd5b506102e8611356565b3480156105fa57600080fd5b5061051f611365565b34801561060f57600080fd5b506101896004803603604081101561062657600080fd5b506001600160a01b038135169060200135611375565b34801561064857600080fd5b50610651611380565b60408051918252519081900360200190f35b34801561066f57600080fd5b506101896004803603602081101561068657600080fd5b50356001600160a01b0316611386565b3480156106a257600080fd5b50610189600480360360208110156106b957600080fd5b50356001600160a01b03166113b9565b3480156106d557600080fd5b506101896113d3565b60035460408051638b9c948960e01b815290516000926001600160a01b031691638b9c9489916004808301926020929190829003018186803b15801561072357600080fd5b505afa158015610737573d6000803e3d6000fd5b505050506040513d602081101561074d57600080fd5b505160408051630d0e30db60e41b8152905191925082916001600160a01b0383169163d0e30db091349160048082019260009290919082900301818588803b15801561079857600080fd5b505af11580156107ac573d6000803e3d6000fd5b50505050506107bc3383346113e3565b5050565b600354604080516301f07db560e01b81526001600160a01b038681166004830152915191909216916301f07db5916024808301926020929190829003018186803b15801561080d57600080fd5b505afa158015610821573d6000803e3d6000fd5b505050506040513d602081101561083757600080fd5b5051610877576040805162461bcd60e51b815260206004820152600a6024820152696e6f742065726337323160b01b604482015290519081900360640190fd5b610882338483611541565b61088d8284836113e3565b505050565b630a85bd0160e11b949350505050565b60035460408051630c91702f60e31b8152815160009384936001600160a01b039091169263648b81789260048083019392829003018186803b1580156108e757600080fd5b505afa1580156108fb573d6000803e3d6000fd5b505050506040513d604081101561091157600080fd5b50805160209091015160055491935091506001600160a01b03808316911614158061094a57506007546001600160a01b03838116911614155b6109855760405162461bcd60e51b815260040180806020018281038252603e815260200180611e41603e913960400191505060405180910390fd5b600780546001600160a01b039384166001600160a01b03199182161790915560058054929093169116179055565b6007546001600160a01b031681565b600354604080516337b1d58560e01b815233600482015290516001600160a01b03909216916337b1d58591602480820192602092909190829003018186803b158015610a0d57600080fd5b505afa158015610a21573d6000803e3d6000fd5b505050506040513d6020811015610a3757600080fd5b50516003811115610a4457fe5b60ff16610a90576040805162461bcd60e51b81526020600482015260156024820152744e6f7420612076616c69642070726564696361746560581b604482015290519081900360640190fd5b60035460408051638b9c948960e01b815290516000926001600160a01b031691638b9c9489916004808301926020929190829003018186803b158015610ad557600080fd5b505afa158015610ae9573d6000803e3d6000fd5b505050506040513d6020811015610aff57600080fd5b5051600354604080516336a8279560e21b81526001600160a01b038881166004830152915193945091169163daa09e5491602480820192602092909190829003018186803b158015610b5057600080fd5b505afa158015610b64573d6000803e3d6000fd5b505050506040513d6020811015610b7a57600080fd5b505115610bf657604080516323b872dd60e01b81523060048201526001600160a01b038581166024830152604482018590529151918616916323b872dd9160648082019260009290919082900301818387803b158015610bd957600080fd5b505af1158015610bed573d6000803e3d6000fd5b50505050610f3c565b806001600160a01b0316846001600160a01b03161415610c7e5760408051627b8a6760e11b8152600481018490526001600160a01b0385811660248301529151869283169162f714ce91604480830192600092919082900301818387803b158015610c6057600080fd5b505af1158015610c74573d6000803e3d6000fd5b5050505050610f3c565b60035460408051646d6174696360d81b8152815190819003600501812063cac39a0560e01b8252600482015290516001600160a01b039092169163cac39a0591602480820192602092909190829003018186803b158015610cde57600080fd5b505afa158015610cf2573d6000803e3d6000fd5b505050506040513d6020811015610d0857600080fd5b50516001600160a01b0385811691161415610e6d576003805460408051621c1bdb60ea1b8152815190819003909301832063cac39a0560e01b84526004840152516001600160a01b039091169163cac39a05916024808301926020929190829003018186803b158015610d7a57600080fd5b505afa158015610d8e573d6000803e3d6000fd5b505050506040513d6020811015610da457600080fd5b50516040805163a9059cbb60e01b81526001600160a01b038681166004830152602482018690529151919092169163a9059cbb9160448083019260209291908290030181600087803b158015610df957600080fd5b505af1158015610e0d573d6000803e3d6000fd5b505050506040513d6020811015610e2357600080fd5b5051610e68576040805162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b604482015290519081900360640190fd5b610f3c565b836001600160a01b031663a9059cbb84846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015610ecd57600080fd5b505af1158015610ee1573d6000803e3d6000fd5b505050506040513d6020811015610ef757600080fd5b5051610f3c576040805162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b604482015290519081900360640190fd5b50505050565b610f4a6115b6565b80610f5457600080fd5b6008546040518291907f010c0265813c273963aa5e8683cf5c45a3b744ba6369c22af0958ec5fcf16b2090600090a3600855565b6002546001600160a01b031681565b610f9f6115b6565b610fa8816115ff565b50565b610fb3611300565b610fbc57600080fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6003546001600160a01b031681565b61101d6118b0565b838214611061576040805162461bcd60e51b815260206004820152600d60248201526c125b9d985b1a5908125b9c1d5d609a1b604482015290519081900360640190fd5b6004805460408051635391f48360e01b8152928301879052516000926001600160a01b0390921691635391f48391602480830192602092919082900301818787803b1580156110af57600080fd5b505af11580156110c3573d6000803e3d6000fd5b505050506040513d60208110156110d957600080fd5b50516003549091506001600160a01b031660005b8681101561127557816001600160a01b03166301f07db589898481811061111057fe5b905060200201356001600160a01b03166040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561116657600080fd5b505afa15801561117a573d6000803e3d6000fd5b505050506040513d602081101561119057600080fd5b5051156111d4576111cf338989848181106111a757fe5b905060200201356001600160a01b03168888858181106111c357fe5b90506020020135611541565b611221565b61122133308888858181106111e557fe5b905060200201358b8b868181106111f857fe5b905060200201356001600160a01b03166001600160a01b03166118f8909392919063ffffffff16565b61125a8489898481811061123157fe5b905060200201356001600160a01b031688888581811061124d57fe5b9050602002013586611952565b61126b83600163ffffffff611c6d16565b92506001016110ed565b5050505050505050565b6008548111156112d6576040805162461bcd60e51b815260206004820152601d60248201527f657863656564206d6178696d756d206465706f73697420616d6f756e74000000604482015290519081900360640190fd5b6108826001600160a01b03841633308463ffffffff6118f816565b6000546001600160a01b031690565b6000546001600160a01b0316331490565b6107bc82338361127f565b6004546001600160a01b031681565b6113336115b6565b61133b611c86565b565b6006602052600090815260409020805460019091015482565b6005546001600160a01b031681565b600154600160a01b900460ff1681565b6107bc8233836107c0565b60085481565b61138e611300565b61139757600080fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6113c1611300565b6113ca57600080fd5b610fa881611c95565b6113db6115b6565b61133b611d03565b6113eb6118b0565b60035460408051636416c18360e01b81526001600160a01b038086166004830152915185939290921691636416c18391602480820192602092909190829003018186803b15801561143b57600080fd5b505afa15801561144f573d6000803e3d6000fd5b505050506040513d602081101561146557600080fd5b50516114ae576040805162461bcd60e51b81526020600482015260136024820152721513d2d15397d393d517d4d5541413d4951151606a1b604482015290519081900360640190fd5b610f3c848484600460009054906101000a90046001600160a01b03166001600160a01b0316635391f48360016040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b15801561151057600080fd5b505af1158015611524573d6000803e3d6000fd5b505050506040513d602081101561153a57600080fd5b5051611952565b60408051632142170760e11b81526001600160a01b038581166004830152306024830152604482018490529151918416916342842e0e9160648082019260009290919082900301818387803b15801561159957600080fd5b505af11580156115ad573d6000803e3d6000fd5b50505050505050565b6002546001600160a01b0316331461133b5760405162461bcd60e51b8152600401808060200182810382526026815260200180611e7f6026913960400191505060405180910390fd5b60035460408051646d6174696360d81b8152815190819003600501812063cac39a0560e01b8252600482015290516000926001600160a01b03169163cac39a05916024808301926020929190829003018186803b15801561165f57600080fd5b505afa158015611673573d6000803e3d6000fd5b505050506040513d602081101561168957600080fd5b5051600354604080516f3837b63cb3b7b726b4b3b930ba34b7b760811b8152815190819003601001812063cac39a0560e01b8252600482015290519293506000926001600160a01b039092169163cac39a0591602480820192602092909190829003018186803b1580156116fc57600080fd5b505afa158015611710573d6000803e3d6000fd5b505050506040513d602081101561172657600080fd5b5051604080516370a0823160e01b8152306004820152905191925084916001600160a01b038516916370a08231916024808301926020929190829003018186803b15801561177357600080fd5b505afa158015611787573d6000803e3d6000fd5b505050506040513d602081101561179d57600080fd5b505110156117dc5760405162461bcd60e51b815260040180806020018281038252602c815260200180611e15602c913960400191505060405180910390fd5b816001600160a01b031663095ea7b382856040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b505050506040513d602081101561186657600080fd5b5050604080516308a960c160e31b81526004810185905290516001600160a01b0383169163454b060891602480830192600092919082900301818387803b15801561159957600080fd5b600154600160a01b900460ff161561133b576040805162461bcd60e51b81526020600482015260066024820152651b1bd8dad95960d21b604482015290519081900360640190fd5b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052610f3c908590611d18565b60035460408051646d6174696360d81b8152815190819003600501812063cac39a0560e01b8252600482015290516000926001600160a01b03169163cac39a05916024808301926020929190829003018186803b1580156119b257600080fd5b505afa1580156119c6573d6000803e3d6000fd5b505050506040513d60208110156119dc57600080fd5b505190506001600160a01b038481169082161415611a02576119fd836115ff565b611aa2565b6003805460408051621c1bdb60ea1b8152815190819003909301832063cac39a0560e01b84526004840152516001600160a01b039091169163cac39a05916024808301926020929190829003018186803b158015611a5f57600080fd5b505afa158015611a73573d6000803e3d6000fd5b505050506040513d6020811015611a8957600080fd5b50516001600160a01b0385811691161415611aa2578093505b604080518082018252606087811b6bffffffffffffffffffffffff199081168284015287821b16607483015260888083018790528351808403909101815260a883018452805160209182012083524281840190815260008781526006835285812094518555905160019094019390935560055460075485516001600160a01b03808d1682860152808c16828901529481018a905260808082018a90528751808303909101815260a082018089526316f1983160e01b905291851660a4820181815260c48301988952835160e4840152835196909416976316f198319791969395909361010490930192908601918190849084905b83811015611bae578181015183820152602001611b96565b50505050905090810190601f168015611bdb5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b158015611bfb57600080fd5b505af1158015611c0f573d6000803e3d6000fd5b50505050836001600160a01b0316856001600160a01b03167f1dadc8d0683c6f9824e885935c1bec6f76816730dcec148dda8cf25a7b9f797b8585604051808381526020018281526020019250505060405180910390a35050505050565b600082820183811015611c7f57600080fd5b9392505050565b6001805460ff60a01b19169055565b6001600160a01b038116611ca857600080fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001805460ff60a01b1916600160a01b179055565b611d2a826001600160a01b0316611e0e565b611d3357600080fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310611d715780518252601f199092019160209182019101611d52565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611dd3576040519150601f19603f3d011682016040523d82523d6000602084013e611dd8565b606091505b509150915081611de757600080fd5b805115610f3c57808060200190516020811015611e0357600080fd5b5051610f3c57600080fd5b3b15159056fe616d6f756e742065786365656473207468697320636f6e74726163742773204d415449432062616c616e636541746c65617374206f6e65206f6620737461746553656e646572206f72206368696c64436861696e20616464726573732073686f756c64206368616e67654f6e6c7920676f7665726e616e636520636f6e747261637420697320617574686f72697a6564a265627a7a72315820af90bf4264f58eb743bcfe1f448541fe7693fe6821f29e1b76d985e33a522baa64736f6c63430005110032", + "nonce": "0x8b", + "chainId": "0xaa36a7" + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "status": "0x1", + "cumulativeGasUsed": "0x10b4441", + "logs": [ + { + "address": "0x332d42a3c83fbc46f27137278018a589c637ce3b", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000724d72eb61e508d81ca701881f2248f092953bf" + ], + "data": "0x", + "blockHash": "0x28a89052310fadb5f07811332a8c04d1752870b21e8ef659a712ce0a7c7ba782", + "blockNumber": "0x605ef4", + "transactionHash": "0x7791e1d6b77d0b8483bc9294d1562089b2257f9e478014154dc9dc6e70ca7afc", + "transactionIndex": "0x63", + "logIndex": "0xde", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000004000000800000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000010000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x7791e1d6b77d0b8483bc9294d1562089b2257f9e478014154dc9dc6e70ca7afc", + "transactionIndex": "0x63", + "blockHash": "0x28a89052310fadb5f07811332a8c04d1752870b21e8ef659a712ce0a7c7ba782", + "blockNumber": "0x605ef4", + "gasUsed": "0x1b98a2", + "effectiveGasPrice": "0x2e2fa16bc", + "from": "0x0724d72eb61e508d81ca701881f2248f092953bf", + "to": null, + "contractAddress": "0x332d42a3c83fbc46f27137278018a589c637ce3b" + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1721057237, + "chain": 11155111, + "commit": "a5fd7d69" +} \ No newline at end of file diff --git a/broadcast/UpgradeStakeManager_Sepolia.s.sol/11155111/run-1721057742.json b/broadcast/UpgradeStakeManager_Sepolia.s.sol/11155111/run-1721057742.json new file mode 100644 index 00000000..eceb3423 --- /dev/null +++ b/broadcast/UpgradeStakeManager_Sepolia.s.sol/11155111/run-1721057742.json @@ -0,0 +1,112 @@ +{ + "transactions": [ + { + "hash": "0x4499d0ecf70c3a39927d5245cac653c02f0f0c33dc82be6a9ce5d37d4615c70a", + "transactionType": "CREATE", + "contractName": null, + "contractAddress": "0x777badc2c75bd4ee5303bf6e90009bd31d8fd3d1", + "function": null, + "arguments": null, + "transaction": { + "from": "0x0724d72eb61e508d81ca701881f2248f092953bf", + "gas": "0x6b19b6", + "value": "0x0", + "input": "0x60806040526023805460ff191690553480156200001b57600080fd5b5060008054610100600160a81b0319168155600180546001600160a01b0319163317908190556040516001600160a01b039190911691907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a360235460ff1615620000c1576040805162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481a5b9a5d195960921b604482015290519081900360640190fd5b6023805460ff19166001179055615fc580620000de6000396000f3fe608060405234801561001057600080fd5b50600436106107175760003560e01c80637d669752116103a8578063b1d23f02116101f4578063e8afa8e81161011a578063f5e95acb116100b8578063fb1ef52c11610087578063fb1ef52c14611826578063fba58f341461184f578063fc0c546a14611857578063ff3db8e31461185f57610717565b8063f5e95acb1461178f578063f771fc87146117f9578063f83d08ba14611816578063f8a3176c1461181e57610717565b8063f24ccbfe116100f4578063f24ccbfe14611697578063f28699fa1461169f578063f2fde38b146116be578063f41a9642146116e457610717565b8063e8afa8e81461164c578063eceec1d314611672578063f1674fdf1461168f57610717565b8063cf30901211610192578063dcd962b211610161578063dcd962b2146115fc578063e568959a1461161f578063e59ee0c614611627578063e6692f491461162f57610717565b8063cf3090121461159b578063d6de07d0146115a3578063d7f5549d146115c2578063d86d53e7146115df57610717565b8063c710e922116101ce578063c710e92214611518578063c7f067cb14611544578063cbf383d514611576578063cd6b83881461159357610717565b8063b1d23f02146114a6578063b65de35e146114c9578063bc8756a9146114e657610717565b80639342c8f4116102d95780639ff1150011610277578063a69df4b511610246578063a69df4b514611462578063a7ab69611461146a578063a8dc889b14611472578063b184be811461147a57610717565b80639ff1150014611397578063a440ab1e146113ba578063a4769071146113d7578063a6854877146113df57610717565b806399d18f6f116102b357806399d18f6f1461132c5780639a8a62431461134f5780639b33f434146113575780639ddbbf851461137457610717565b80639342c8f4146112dc57806396a93224146112f9578063987ab9db1461132457610717565b806386a22666116103465780638f32d59b116103205780638f32d59b146112a7578063900cf0cf146112af57806391460149146112b757806391f1a3a5146112d457610717565b806386a226661461127a578063883b455f146112975780638da5cb5b1461129f57610717565b80637f952d95116103825780637f952d951461118057806381254e1214611188578063817b1cd21461124f578063858a7c031461125757610717565b80637d6697521461113e5780637ed4b27c146111465780637f4b43231461116357610717565b806341b3d185116105675780635ab1bd53116104985780637060054d116104365780637854f354116104055780637854f354146110eb57806378f84a44146111085780637b1039991461112e5780637c7eaf1a1461113657610717565b80637060054d146110cb578063715018a6146110d357806376671808146110db57806377939d10146110e357610717565b80636352211e116104725780636352211e14610fa05780636365679814610fbd57806368cb812a14610fe95780636901b2531461109957610717565b80635ab1bd5314610f015780635e47655f14610f0957806360c8d12214610f7757610717565b80634fdd20f11161050557806354b8c601116104df57806354b8c60114610ecc5780635508d8e114610ed457806356342d8c14610edc5780635aa6e67514610ef957610717565b80634fdd20f114610ca657806352b8115d14610d6d5780635325e14414610e0557610717565b80634b341aed116105415780634b341aed14610c3e5780634c02550014610c645780634e3c83f114610c965780634fd101d714610c9e57610717565b806341b3d18514610bf2578063451b598514610bfa57806348ab8b2a14610c0257610717565b80632079fb9a1161064c5780632fa9d18b116105ea57806335aa2e44116105b957806335aa2e4414610ac85780633862da0b14610b8157806339610f7814610ba75780633c34355614610bc457610717565b80632fa9d18b14610a0c57806330cbe57114610a9b57806331c2273b14610ab85780633427458614610ac057610717565b80632649263a116106265780632649263a146108f257806328cc4e41146109235780632cf44a431461094e5780632e17de78146109ef57610717565b80632079fb9a1461089757806325316411146108b457806325726df2146108bc57610717565b8063174e6832116106b95780631ae4818f116106935780631ae4818f1461082f5780631c404cec146108375780631dd6b9b1146108545780631e9b12ef1461087157610717565b8063174e6832146107e4578063178c2c831461080a57806317c2b9101461082757610717565b80630e15561a116106f55780630e15561a146107935780630ebb172a1461079b57806316827b1b146107a35780631705a3bd146107c057610717565b806306cfb1041461071c578063078a13b11461073b5780630cccfc5814610779575b600080fd5b6107396004803603602081101561073257600080fd5b503561187c565b005b6107396004803603608081101561075157600080fd5b506001600160a01b038135811691602081013582169160408201358116916060013516611889565b610781611901565b60408051918252519081900360200190f35b610781611907565b61078161190d565b610739600480360360208110156107b957600080fd5b5035611913565b6107c861199c565b604080516001600160a01b039092168252519081900360200190f35b610781600480360360208110156107fa57600080fd5b50356001600160a01b03166119ab565b6107396004803603602081101561082057600080fd5b5035611a35565b610781611cc2565b6107c8611cc8565b6107396004803603602081101561084d57600080fd5b5035611cd7565b6107396004803603602081101561086a57600080fd5b5035611cf0565b6107396004803603602081101561088757600080fd5b50356001600160a01b0316611cfd565b6107c8600480360360208110156108ad57600080fd5b5035611d3a565b610781611d61565b6108d9600480360360208110156108d257600080fd5b5035611d67565b6040805192835260208301919091528051918290030190f35b61090f6004803603602081101561090857600080fd5b5035611d80565b604080519115158252519081900360200190f35b6107396004803603606081101561093957600080fd5b50803590602081013590604001351515611dbb565b6107396004803603602081101561096457600080fd5b810190602081018135600160201b81111561097e57600080fd5b82018360208201111561099057600080fd5b803590602001918460208302840111600160201b831117156109b157600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611de0945050505050565b61073960048036036020811015610a0557600080fd5b5035611e04565b610781600480360360a0811015610a2257600080fd5b8135916020810135916040820135916001600160a01b036060820135169181019060a081016080820135600160201b811115610a5d57600080fd5b820183602082011115610a6f57600080fd5b803590602001918460608302840111600160201b83111715610a9057600080fd5b509092509050611e19565b61073960048036036020811015610ab157600080fd5b503561212a565b6107c861213f565b61078161214e565b610ae560048036036020811015610ade57600080fd5b5035612154565b604051808e81526020018d81526020018c81526020018b81526020018a8152602001896001600160a01b03166001600160a01b03168152602001886001600160a01b03166001600160a01b03168152602001876003811115610b4357fe5b60ff1681526020018681526020018581526020018481526020018381526020018281526020019d505050505050505050505050505060405180910390f35b61078160048036036020811015610b9757600080fd5b50356001600160a01b03166121c5565b61078160048036036020811015610bbd57600080fd5b50356121d7565b61073960048036036040811015610bda57600080fd5b506001600160a01b0381358116916020013516612238565b6107816122f1565b6107816122f7565b61073960048036036080811015610c1857600080fd5b508035906001600160a01b036020820135811691604081013590911690606001356122fd565b61078160048036036020811015610c5457600080fd5b50356001600160a01b03166123a3565b61090f60048036036060811015610c7a57600080fd5b50803590602081013590604001356001600160a01b03166124da565b6107816124fb565b610781612501565b610739600480360360a0811015610cbc57600080fd5b6001600160a01b0382351691602081013591604082013591606081013515159181019060a081016080820135600160201b811115610cf957600080fd5b820183602082011115610d0b57600080fd5b803590602001918460018302840111600160201b83111715610d2c57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612507945050505050565b610739600480360360c0811015610d8357600080fd5b6001600160a01b038235169160208101359160408201359160608101359160808201351515919081019060c0810160a0820135600160201b811115610dc757600080fd5b820183602082011115610dd957600080fd5b803590602001918460018302840111600160201b83111715610dfa57600080fd5b509092509050612525565b610e2260048036036020811015610e1b57600080fd5b5035612648565b60405180868152602001858152602001846001600160a01b03166001600160a01b031681526020018315151515815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610e8d578181015183820152602001610e75565b50505050905090810190601f168015610eba5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b61090f61270e565b610781612717565b6107c860048036036020811015610ef257600080fd5b503561271d565b6107c861273b565b6107c861274f565b61078160048036036020811015610f1f57600080fd5b810190602081018135600160201b811115610f3957600080fd5b820183602082011115610f4b57600080fd5b803590602001918460018302840111600160201b83111715610f6c57600080fd5b50909250905061275f565b61073960048036036060811015610f8d57600080fd5b5080359060208101359060400135612766565b6107c860048036036020811015610fb657600080fd5b50356127cf565b61073960048036036040811015610fd357600080fd5b506001600160a01b03813516906020013561281b565b61073960048036036060811015610fff57600080fd5b813591602081013591810190606081016040820135600160201b81111561102557600080fd5b82018360208201111561103757600080fd5b803590602001918460018302840111600160201b8311171561105857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612832945050505050565b61090f600480360360608110156110af57600080fd5b50803590602081013590604001356001600160a01b0316612978565b610781612990565b610739612996565b6107816129f1565b6107816129f7565b6107396004803603602081101561110157600080fd5b50356129fd565b6107816004803603602081101561111e57600080fd5b50356001600160a01b0316612a16565b6107c8612a28565b610781612a37565b610781612a3d565b6107816004803603602081101561115c57600080fd5b5035612a43565b6107816004803603602081101561117957600080fd5b5035612a9a565b610781612aaf565b610739600480360360a081101561119e57600080fd5b6001600160a01b0382351691602081013591604082013591606081013515159181019060a081016080820135600160201b8111156111db57600080fd5b8201836020820111156111ed57600080fd5b803590602001918460018302840111600160201b8311171561120e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612ab5945050505050565b610781612acc565b6107396004803603604081101561126d57600080fd5b5080359060200135612ad2565b6107396004803603602081101561129057600080fd5b5035612b18565b6107c8612b29565b6107c8612b3d565b61090f612b4c565b610781612b8f565b610739600480360360208110156112cd57600080fd5b5035612b95565b610781612bab565b610739600480360360208110156112f257600080fd5b5035612bb1565b6107396004803603606081101561130f57600080fd5b50803590602081013590604001351515612bc6565b6107c8612be5565b6107396004803603604081101561134257600080fd5b5080359060200135612bf4565b610781612c5a565b6107396004803603602081101561136d57600080fd5b5035612c60565b6107396004803603604081101561138a57600080fd5b5080359060200135612d1c565b610739600480360360408110156113ad57600080fd5b5080359060200135612d82565b610739600480360360208110156113d057600080fd5b5035612e75565b610781612e8c565b610739600480360360808110156113f557600080fd5b813591602081013591604082013515159190810190608081016060820135600160201b81111561142457600080fd5b82018360208201111561143657600080fd5b803590602001918460018302840111600160201b8311171561145757600080fd5b509092509050612e92565b610739612f43565b610781612f55565b610781612f5b565b6107396004803603604081101561149057600080fd5b506001600160a01b038135169060200135612f61565b610739600480360360408110156114bc57600080fd5b5080359060200135612f75565b610781600480360360208110156114df57600080fd5b5035612f88565b61090f600480360360608110156114fc57600080fd5b50803590602081013590604001356001600160a01b0316612fd6565b6107396004803603604081101561152e57600080fd5b50803590602001356001600160a01b0316612fed565b61090f6004803603606081101561155a57600080fd5b50803590602081013590604001356001600160a01b03166130a8565b6107396004803603602081101561158c57600080fd5b50356130b7565b610781613140565b61090f613146565b610739600480360360208110156115b957600080fd5b5035151561314f565b610781600480360360208110156115d857600080fd5b50356132a1565b610739600480360360208110156115f557600080fd5b50356132b3565b6107396004803603604081101561161257600080fd5b50803590602001356132c8565b610781613330565b6108d9613336565b6107396004803603602081101561164557600080fd5b503561333f565b6107396004803603602081101561166257600080fd5b50356001600160a01b03166133fb565b6107816004803603602081101561168857600080fd5b503561347b565b6107c861348d565b6107c861349c565b610739600480360360208110156116b557600080fd5b503515156134ab565b610739600480360360208110156116d457600080fd5b50356001600160a01b03166134c6565b610739600480360360408110156116fa57600080fd5b81359190810190604081016020820135600160201b81111561171b57600080fd5b82018360208201111561172d57600080fd5b803590602001918460018302840111600160201b8311171561174e57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506134e0945050505050565b61073960048036036101208110156117a657600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135821691608082013581169160a081013582169160c082013581169160e081013582169161010090910135166136e5565b6107396004803603602081101561180f57600080fd5b5035613888565b6107396138a3565b6107c86138b3565b6107396004803603606081101561183c57600080fd5b50803590602081013590604001356138c2565b6107816139dd565b6107c86139e3565b6107396004803603602081101561187557600080fd5b50356139f2565b611884613a07565b600f55565b611891613a07565b61189a81613a55565b6118a357600080fd5b60238054610100600160a81b0319169055602580546001600160a01b03199081166001600160a01b03938416179091556006805482169583169590951790945560058054851693821693909317909255600780549093169116179055565b60155481565b60135481565b60085481565b61191b613a07565b8061192557600080fd5b60055460105460408051630f1980a560e41b8152600481018590526024810192909252516001600160a01b039092169163f1980a509160448082019260009290919082900301818387803b15801561197c57600080fd5b505af1158015611990573d6000803e3d6000fd5b50505060109190915550565b602c546001600160a01b031681565b60065460408051632f745c5960e01b81526001600160a01b038481166004830152600060248301819052925192931691632f745c5991604480820192602092909190829003018186803b158015611a0157600080fd5b505afa158015611a15573d6000803e3d6000fd5b505050506040513d6020811015611a2b57600080fd5b505190505b919050565b80611a3f81613a74565b60026000838152601a6020526040902060060154600160a01b900460ff166003811115611a6857fe5b14611aa7576040805162461bcd60e51b815260206004820152600a602482015269139bdd081a985a5b195960b21b604482015290519081900360640190fd5b6000828152601a602052604090206003015415611aff576040805162461bcd60e51b8152602060048201526011602482015270416c726561647920756e7374616b696e6760781b604482015290519081900360640190fd5b6009546000838152601a6020526040902060040154811015611b61576040805162461bcd60e51b8152602060048201526016602482015275125b98dbdb5c1b195d19481a985a5b081c195c9a5bd960521b604482015290519081900360640190fd5b6000838152601a6020526040902054600c54811015611b7f57600080fd5b6000848152601a60205260409020600601546001600160a01b03168015611bf457806001600160a01b031663a69df4b56040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611bdb57600080fd5b505af1158015611bef573d6000803e3d6000fd5b505050505b6000858152601a60205260409020600a0154611c2490611c1b90849063ffffffff613afe16565b60016000613b10565b6000858152601a602052604080822060068101805460ff60a01b1916600160a01b1790556005908101549054825163f92ec5af60e01b8152600481018a90526001600160a01b039283166024820181905293519394929091169263f92ec5af9260448084019391929182900301818387803b158015611ca257600080fd5b505af1158015611cb6573d6000803e3d6000fd5b50505050505050505050565b60175481565b6007546001600160a01b031681565b80611ce181613a74565b611cec826001613bcc565b5050565b611cf8613a07565b600955565b611d05613a07565b6001600160a01b038116611d1857600080fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b60268181548110611d4757fe5b6000918252602090912001546001600160a01b0316905081565b600e5481565b601e602052600090815260409020805460019091015482565b6000818152601a6020526040812060068101548154600390920154600954611db593600160a01b90930460ff16929190613be0565b92915050565b611dc3613c17565b82611dcd81613a74565b611dda8484846000613c58565b50505050565b611de8612b4c565b611df157600080fd5b8051611cec906026906020840190615e39565b80611e0e81613a74565b611cec826000613e32565b6002546000906001600160a01b03163314611e3357600080fd5b600954601d546000908190611e46615e9e565b6026546040805191840180835260208082028401019091528015611e74578160200160208202803883390190505b5060408083019190915260268054825160208083028201810190945281815292830182828015611ecd57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611eaf575b50505050506060820152600060208201526026546080820152611eee615ecd565b6026546040805191850180835260208082028401019091528015611f1c578160200160208202803883390190505b50602082015260005b888110156120eb576000611f738e8c8c85818110611f3f57fe5b9050606002016003806020026040519081016040528092919082600360200280828437600092019190915250613ee5915050565b9050856001600160a01b0316816001600160a01b03161415611f9557506120e3565b856001600160a01b0316816001600160a01b03161015611fb557506120eb565b6001600160a01b0381166000908152601b6020908152604080832054808452601a909252909120805460068201546003909201548087529091600160a01b900460ff169061200790829084908e613be0565b15612092576000838152601a60205260409020600a0154939850889361204690839061203a908d9063ffffffff613afe16565b9063ffffffff613afe16565b8651909a50156120805782866020015187604001518151811061206557fe5b6020908102919091010152604086018051600101905261208d565b61208a8785613fe8565b96505b6120de565b60028160038111156120a057fe5b14156120de578287604001518860000151815181106120bb57fe5b602090810291909101810191909152875160019081018952908801805190910190525b505050505b600101611f25565b506120f7826000613fe8565b91506121198d8b878e86604001518760000151876020015188604001516140c5565b9d9c50505050505050505050505050565b8061213481613a74565b611cec826001613e32565b6006546001600160a01b031681565b60165481565b601a60205260009081526040902080546001820154600283015460038401546004850154600586015460068701546007880154600889015460098a0154600a8b0154600b909b0154999a98999798969795966001600160a01b039586169695851695600160a01b90950460ff16948d565b601b6020526000908152604090205481565b6000818152601a602052604081206003015481906121fc576121f88361422d565b9150505b6000838152601a602052604090206009015461223190600190612225908463ffffffff613afe16565b9063ffffffff6142a916565b9392505050565b612240613a07565b60038054602b80546001600160a01b038084166001600160a01b0319928316179283905592811686841617909355602c805490931684831617909255604080516370a0823160e01b81523060048201529051611cec93909216916370a0823191602480820192602092909190829003018186803b1580156122c057600080fd5b505afa1580156122d4573d6000803e3d6000fd5b505050506040513d60208110156122ea57600080fd5b50516142be565b600c5481565b60295481565b612305613a07565b6000848152601a60205260409020600601546001600160a01b03168061232a57600080fd5b6040805163abf59fc960e01b81526001600160a01b03868116600483015285811660248301526044820185905291519183169163abf59fc99160648082019260009290919082900301818387803b15801561238457600080fd5b505af1158015612398573d6000803e3d6000fd5b505050505050505050565b60006001600160a01b03821615806124315750600654604080516370a0823160e01b81526001600160a01b038581166004830152915191909216916370a08231916024808301926020929190829003018186803b15801561240357600080fd5b505afa158015612417573d6000803e3d6000fd5b505050506040513d602081101561242d57600080fd5b5051155b1561243e57506000611a30565b60065460408051632f745c5960e01b81526001600160a01b0385811660048301526000602483018190529251601a949190911691632f745c59916044808301926020929190829003018186803b15801561249757600080fd5b505afa1580156124ab573d6000803e3d6000fd5b505050506040513d60208110156124c157600080fd5b5051815260208101919091526040016000205492915050565b6000836124e68161445d565b6124f2848460016144cb565b95945050505050565b600f5481565b60105481565b61250f613c17565b61251e85858585856000614571565b5050505050565b333014612567576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b61257687888860006001614623565b6125848560095460016146f0565b60006125c888868686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061485492505050565b6005546040805163e12ab1af60e01b815260048101849052602481018a90526044810189905290519293506001600160a01b039091169163e12ab1af9160648082019260009290919082900301818387803b15801561262657600080fd5b505af115801561263a573d6000803e3d6000fd5b505050505050505050505050565b60208080526000918252604091829020805460018083015460028085015460038601805489516101009682161596909602600019011692909204601f8101889004880285018801909852878452939691956001600160a01b03851695600160a01b90950460ff16949392908301828280156127045780601f106126d957610100808354040283529160200191612704565b820191906000526020600020905b8154815290600101906020018083116126e757829003601f168201915b5050505050905085565b60195460ff1681565b60125481565b6000908152601a60205260409020600601546001600160a01b031690565b60005461010090046001600160a01b031681565b6004546001600160a01b03165b90565b6000806000fd5b61276e613a07565b60255460408051602481018690526044810185905260648082018590528251808303909101815260849091019091526020810180516001600160e01b0316633064689160e11b1790526127ca916001600160a01b031690614c61565b505050565b600654604080516331a9108f60e11b81526004810184905290516000926001600160a01b031691636352211e916024808301926020929190829003018186803b158015611a0157600080fd5b612823613c17565b611cec82338360006001614623565b6017546040805133602080830191909152818301879052825180830384018152606090920190925280519101206128719184908463ffffffff614c8916565b6128b4576040805162461bcd60e51b815260206004820152600f60248201526e2bb937b7339030b1b190383937b7b360891b604482015290519081900360640190fd5b336000908152601f60205260408120546128d590859063ffffffff6142a916565b6022549091506128eb908263ffffffff6142a916565b6022556005546040805163122b648160e01b81523360048201526024810184905290516001600160a01b039092169163122b64819160448082019260009290919082900301818387803b15801561294157600080fd5b505af1158015612955573d6000803e3d6000fd5b5050336000818152601f60205260408120889055611dda93509091508390614ddf565b6000836129848161445d565b6124f2848460006144cb565b600a5481565b61299e612b4c565b6129a757600080fd5b6001546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600180546001600160a01b0319169055565b60095481565b60185481565b612a05613a07565b612a138160095460016146f0565b50565b601f6020526000908152604090205481565b6004546001600160a01b031681565b602a5481565b600b5481565b600081612a4f8161445d565b612a5883614ec9565b6000838152601a6020526040812060090154612a7b90600163ffffffff6142a916565b6000858152601a60205260409020600160099091015592505050919050565b6000908152601a60205260409020600a015490565b601d5490565b612abd613c17565b61251e85858585856001614571565b60115481565b81612adc8161445d565b6000838152601a60205260409020600a0154612afe908363ffffffff6142a916565b6000938452601a6020526040909320600a01929092555050565b612b20613a07565b612a13816142be565b60235461010090046001600160a01b031681565b6001546001600160a01b031690565b604080517f6d617469632e6e6574776f726b2e70726f78792e6f776e6572000000000000008152905190819003601901902054336001600160a01b039091161490565b60095490565b612b9d613a07565b612a138160095460006146f0565b60275481565b80612bbb81613a74565b611cec826000613bcc565b612bce613c17565b82612bd881613a74565b611dda8484846001613c58565b6002546001600160a01b031681565b612bfc613c17565b602554604080516024810185905260448101849052306064808301919091528251808303909101815260849091019091526020810180516001600160e01b031663561ad5c960e11b179052611cec916001600160a01b031690614c61565b60225481565b612c68613a07565b6005546016546040805163a3b1d8cb60e01b8152600481018590526024810192909252516001600160a01b039092169163a3b1d8cb9160448082019260009290919082900301818387803b158015612cbf57600080fd5b505af1158015612cd3573d6000803e3d6000fd5b505050506064811115612d17576040805162461bcd60e51b8152602060048201526007602482015266746f6f2062696760c81b604482015290519081900360640190fd5b601655565b612d24612b4c565b612d2d57600080fd5b602554604080516024810185905260448082018590528251808303909101815260649091019091526020810180516001600160e01b0316639ddbbf8560e01b179052611cec916001600160a01b031690614c61565b81612d8c8161445d565b6000821315612de55760195460ff16612de5576040805162461bcd60e51b815260206004820152601660248201527511195b1959d85d1a5bdb881a5cc8191a5cd8589b195960521b604482015290519081900360640190fd5b6000838152601a602052604090206003015480612e0d57612e0883600080613b10565b612e50565b600954811115612e50576040805162461bcd60e51b8152602060048201526009602482015268756e7374616b696e6760b81b604482015290519081900360640190fd5b60008312612e6757612e628484614ed8565b611dda565b611dda848460001902612ad2565b612e7d613a07565b80612e8757600080fd5b600e55565b601c5490565b612e9a613c17565b6025546040516024810187815260448201879052851515606483015260806084830190815260a4830185905261251e936001600160a01b03169263a685487760e01b928a928a928a928a928a9260c40184848082843760008184015260408051601f19601f9093018316909401848103909201845252506020810180516001600160e01b03199a909a166001600160e01b03909a169990991790985250614c6195505050505050565b612f4b613a07565b612f53614f13565b565b60085490565b60245481565b612f69613a07565b611cec82826001614ddf565b612f7d613a07565b600c91909155600d55565b6000818152601a60205260408120600301548190612fad57612fa98361422d565b5090505b6000838152601a602052604090206001908101546122319190612225908463ffffffff613afe16565b6000612fe58484846000614f1f565b949350505050565b612ff5613a07565b306001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561303857600080fd5b505afa15801561304c573d6000803e3d6000fd5b505050506040513d602081101561306257600080fd5b50516001600160a01b03161461307757600080fd5b6000918252601a602052604090912060060180546001600160a01b0319166001600160a01b03909216919091179055565b6000612fe58484846001614f1f565b6130bf613a07565b806130c957600080fd5b600554600b5460408051632dbe9d3160e21b8152600481018590526024810192909252516001600160a01b039092169163b6fa74c49160448082019260009290919082900301818387803b15801561312057600080fd5b505af1158015613134573d6000803e3d6000fd5b505050600b9190915550565b60145481565b60005460ff1681565b336000908152601b6020908152604080832054808452601a9092529091206006810154815460039092015460095461319493600160a01b90930460ff16929190613be0565b6131d5576040805162461bcd60e51b815260206004820152600d60248201526c3737ba103b30b634b230ba37b960991b604482015290519081900360640190fd5b6000818152601a60205260409020600601546001600160a01b03168061323b576040805162461bcd60e51b815260206004820152601660248201527511195b1959d85d1a5bdb881a5cc8191a5cd8589b195960521b604482015290519081900360640190fd5b604080516303dd464160e51b8152841515600482015290516001600160a01b03831691637ba8c82091602480830192600092919082900301818387803b15801561328457600080fd5b505af1158015613298573d6000803e3d6000fd5b50505050505050565b60216020526000908152604090205481565b806132bd81613a74565b611cec8260006150ae565b816132d281613a74565b6132db83614ec9565b602554604080516024810186905260448082018690528251808303909101815260649091019091526020810180516001600160e01b0316636e6cb15960e11b1790526127ca916001600160a01b031690614c61565b60285481565b601c54601d5482565b613347613a07565b6000811161335457600080fd5b600554600a5460408051635071805360e11b8152600481018590526024810192909252516001600160a01b039092169163a0e300a69160448082019260009290919082900301818387803b1580156133ab57600080fd5b505af11580156133bf573d6000803e3d6000fd5b505050600a8290555060088190556133de81600463ffffffff61528c16565b60158190556009546133f59163ffffffff613afe16565b60185550565b613403612b4c565b61340c57600080fd5b6001600160a01b03811661341f57600080fd5b6002546040516001600160a01b038084169216907f211c9015fc81c0dbd45bd99f0f29fc1c143bfd53442d5ffd722bbbef7a887fe990600090a3600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000908152601a602052604090205490565b602b546001600160a01b031681565b6005546001600160a01b031681565b6134b3613a07565b6019805460ff1916911515919091179055565b6134ce612b4c565b6134d757600080fd5b612a13816152ae565b816134ea81613a74565b60006134f58361531d565b600954600f54600087815260216020526040902054929350909161351e9163ffffffff613afe16565b811015613560576040805162461bcd60e51b815260206004820152600b60248201526a139bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6000858152601a602090815260408083206005908101549054915163b80fbce560e01b8152600481018a81526001600160a01b039283166024830181905288841660448401526080606484019081528b5160848501528b519197949095169563b80fbce5958d9589958c958f95909460a490920192918601918190849084905b838110156135f85781810151838201526020016135e0565b50505050905090810190601f1680156136255780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b15801561364757600080fd5b505af115801561365b573d6000803e3d6000fd5b5050506000878152601a60205260409020600301541515905061368a57613681816153d6565b61368a836154e0565b6001600160a01b039081166000908152601b60209081526040808320600019905594909216808252848220889055968152601a825283812060050180546001600160a01b031916909717909655602190529320929092555050565b60235460ff161561372e576040805162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481a5b9a5d195960921b604482015290519081900360640190fd5b6023805460ff1916600117905561374481613a55565b61378e576040805162461bcd60e51b8152602060048201526016602482015275185d58dd1a5bdb881a5b5c1b081a5b98dbdc9c9958dd60521b604482015290519081900360640190fd5b602580546001600160a01b03199081166001600160a01b038481169190911790925560008054610100600160a81b031916610100878516021790556004805482168c84161790556002805482168b84161790556003805482168a84161790556006805482168984161790556005805482168884161790556007805490911691861691909117905561381e826152ae565b5050612000600855505060016009819055610376600a90815569044664c7bf6451f00000600b55670de0b6b3a7640000600c819055600d55610400600e556064600f55600760105560128290556108006015556016556019805460ff191690911790555050505050565b613890613a07565b6009546133f5908263ffffffff613afe16565b6138ab613a07565b612f536155fa565b6025546001600160a01b031681565b6007821161390b576040805162461bcd60e51b815260206004820152601160248201527024b73b30b634b21036b4b3b930ba34b7b760791b604482015290519081900360640190fd5b6000838152601a6020526040808220600601548151636e7ce59160e01b81523360048201526024810185905291516001600160a01b0390911692636e7ce591926044808201939182900301818387803b15801561396757600080fd5b505af115801561397b573d6000803e3d6000fd5b5050506000838152601a6020526040808220600601548151632830728d60e21b81523360048201526024810186905291516001600160a01b03909116935063a0c1ca349260448084019391929182900301818387803b15801561328457600080fd5b600d5481565b6003546001600160a01b031681565b806139fc81613a74565b611cec8260016150ae565b60005461010090046001600160a01b03163314612f535760405162461bcd60e51b8152600401808060200182810382526026815260200180615f6b6026913960400191505060405180910390fd5b60006001600160a01b038216613a6d57506000611a30565b503b151590565b600654604080516331a9108f60e11b815260048101849052905133926001600160a01b031691636352211e916024808301926020929190829003018186803b158015613abf57600080fd5b505afa158015613ad3573d6000803e3d6000fd5b505050506040513d6020811015613ae957600080fd5b50516001600160a01b031614612a1357600080fd5b60008282018381101561223157600080fd5b80613baa576000831315613b3957601c54613b31908463ffffffff613afe16565b601c55613b5d565b6000831215613b5d57601c54613b5990600085900363ffffffff6142a916565b601c555b6000821315613b8157601d54613b79908363ffffffff613afe16565b601d55613ba5565b6000821215613ba557601d54613ba190600084900363ffffffff6142a916565b601d555b6127ca565b6000818152601e60205260409020805484018155600101805483019055505050565b613bd582614ec9565b611cec823383615609565b60008084118015613bf85750821580613bf857508183115b80156124f257506001856003811115613c0d57fe5b1495945050505050565b60005460ff1615612f53576040805162461bcd60e51b81526020600482015260066024820152651b1bd8dad95960d21b604482015290519081900360640190fd5b6000848152601a602052604090206003015415613cab576040805162461bcd60e51b815260206004820152600c60248201526b4e6f2072657374616b696e6760a01b604482015290519081900360640190fd5b8215613cbd57613cbd333085846156e0565b613cc684614ec9565b8115613d0d576000848152601a60205260409020600190810154613cf6919061222590869063ffffffff613afe16565b6000858152601a6020526040902060019081015592505b601154600090613d23908563ffffffff613afe16565b60118190556000868152601a6020526040902054909150613d4a908563ffffffff613afe16565b6000868152601a6020526040812091909155613d6890859080613b10565b6005546040805163532e19a960e01b81526004810188905290516001600160a01b039092169163532e19a99160248082019260009290919082900301818387803b158015613db557600080fd5b505af1158015613dc9573d6000803e3d6000fd5b50506005546000888152601a6020526040808220548151631585a9f360e21b8152600481018c905260248101919091526044810187905290516001600160a01b039093169450635616a7cc93506064808201939182900301818387803b15801561238457600080fd5b600082815260208052604090205415613e4a57600080fd5b6000828152601a602052604090206006810154600290910154600160a01b90910460ff169015801590613e8c57506000838152601a6020526040902060030154155b8015613eb857506001816003811115613ea157fe5b1480613eb857506002816003811115613eb657fe5b145b613ec157600080fd5b600954600090613ed890600163ffffffff613afe16565b9050611dda8482856146f0565b805160208201516040830151600092919060ff167f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115613f2d5760009350505050611db5565b601b8160ff161015613f3d57601b015b8060ff16601b14158015613f5557508060ff16601c14155b15613f665760009350505050611db5565b60408051600080825260208083018085528a905260ff85168385015260608301879052608083018690529251909260019260a080820193601f1981019281900390910190855afa158015613fbe573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116613fde57600080fd5b9695505050505050565b613ff0615e9e565b826080015183602001511080156140345750816001600160a01b0316836060015184602001518151811061402057fe5b60200260200101516001600160a01b031614155b156140b557601b6000846060015185602001518151811061405157fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054836040015184600001518151811061408e57fe5b60209081029190910181019190915283516001908101855290840180519091019052613ff0565b5050602081018051600101905290565b601c546000906140f2600161203a60036140e685600263ffffffff6157e116565b9063ffffffff61528c16565b88101561413c576040805162461bcd60e51b8152602060048201526013602482015272322f332b31206e6f6e2d6d616a6f726974792160681b604482015290519081900360640190fd5b60006141498b8a84615808565b9050600061416760646140e6601654856157e190919063ffffffff16565b6001600160a01b038c166000908152601b6020908152604080832054808452601a909252909120600181015492935090916141a8908463ffffffff613afe16565b600182015560178b905560006141f56141e68e6140e66a084595161401484a0000006141da8a8a63ffffffff6142a916565b9063ffffffff6157e116565b6024549063ffffffff613afe16565b90506142028b8b8361595c565b602481905561421289898361595c565b61421a615990565b50929d9c50505050505050505050505050565b6000818152601a602052604081208054600a90910154829190829061425990839063ffffffff613afe16565b6000868152601a60205260409020600b0154602454919250900361429d86846142976a084595161401484a0000006140e6868863ffffffff6157e116565b85615a05565b94509450505050915091565b6000828211156142b857600080fd5b50900390565b602b54604080516370a0823160e01b8152306004820152905183926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561430857600080fd5b505afa15801561431c573d6000803e3d6000fd5b505050506040513d602081101561433257600080fd5b50511015614377576040805162461bcd60e51b815260206004820152600d60248201526c4c61636b696e67204d4154494360981b604482015290519081900360640190fd5b602b54602c546040805163095ea7b360e01b81526001600160a01b039283166004820152602481018590529051919092169163095ea7b39160448083019260209291908290030181600087803b1580156143d057600080fd5b505af11580156143e4573d6000803e3d6000fd5b505050506040513d60208110156143fa57600080fd5b5050602c54604080516308a960c160e31b81526004810184905290516001600160a01b039092169163454b06089160248082019260009290919082900301818387803b15801561444957600080fd5b505af115801561251e573d6000803e3d6000fd5b6000818152601a60205260409020600601546001600160a01b03163314612a13576040805162461bcd60e51b815260206004820152601860248201527f496e76616c696420636f6e747261637420616464726573730000000000000000604482015290519081900360640190fd5b6000806144d783615a99565b604080516323b872dd60e01b81526001600160a01b038781166004830152306024830152604482018990529151929350600092918416916323b872dd9160648082019260209290919082900301818787803b15801561453557600080fd5b505af1158015614549573d6000803e3d6000fd5b505050506040513d602081101561455f57600080fd5b50519050836124f2576124f2866142be565b60105461457c612aaf565b106145be576040805162461bcd60e51b815260206004820152600d60248201526c6e6f206d6f726520736c6f747360981b604482015290519081900360640190fd5b600c5485101561460a576040805162461bcd60e51b81526020600482015260126024820152711b9bdd08195b9bdd59da0819195c1bdcda5d60721b604482015290519081900360640190fd5b6146178633868885614623565b61329886868585614854565b600d5483101561466a576040805162461bcd60e51b815260206004820152600d60248201526c199959481d1bdbc81cdb585b1b609a1b604482015290519081900360640190fd5b614685843061467f868663ffffffff613afe16565b846156e0565b602254614698908463ffffffff613afe16565b6022556005546040805163a449d79560e01b81526001600160a01b038881166004830152602482018790529151919092169163a449d79591604480830192600092919082900301818387803b15801561238457600080fd5b6146f983614ec9565b6000838152601a602052604081205490614712856127cf565b6000868152601a6020526040902060038101869055600a810154600690910154919250906001600160a01b0316801561479957806001600160a01b031663f83d08ba6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561478057600080fd5b505af1158015614794573d6000803e3d6000fd5b505050505b6000878152601a60205260409020600501546147bd906001600160a01b03166153d6565b6147c8878487615609565b60006009548711156147da57866147dd565b60005b90506147f183860160000360001983613b10565b60055460408051635e04d48360e01b81526001600160a01b038781166004830152602482018c9052604482018b90526064820189905291519190921691635e04d48391608480830192600092919082900301818387803b15801561262657600080fd5b6000806148608361531d565b600954601254600554601154939450919290916001600160a01b031690600090614890908a63ffffffff613afe16565b905080601181905550604051806101a001604052808a8152602001600181526020018581526020016000815260200160008152602001866001600160a01b03168152602001896148e157600061496d565b600754600480546040805163d4ad267360e01b81529283018990526001600160a01b03888116602485015291821660448401525192169163d4ad2673916064808201926020929091908290030181600087803b15801561494057600080fd5b505af1158015614954573d6000803e3d6000fd5b505050506040513d602081101561496a57600080fd5b50515b6001600160a01b031681526020016001815260006020808301829052604080840183905260016060808601829052608080870186905260245460a0978801528a8652601a855294839020875181559387015191840191909155908501516002830155840151600380830191909155918401516004820155918301516005830180546001600160a01b039283166001600160a01b03199182161790915560c08501516006850180549190931691161780825560e08501519260ff60a01b1990911690600160a01b908490811115614a3f57fe5b0217905550610100820151600782015561012082015160088201556101408201516009820155610160820151600a82015561018090910151600b9091015560008381526021602052604080822086905560065481516340c10f1960e01b81526001600160a01b038e8116600483015260248201889052925192909116926340c10f199260448084019382900301818387803b158015614add57600080fd5b505af1158015614af1573d6000803e3d6000fd5b5050506001600160a01b0386166000908152601b60205260408120859055614b1e91508a90600190613b10565b836020600085815260200190815260200160002060010181905550816001600160a01b03166333a8383c868986888e876040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b0316815260200180602001868152602001858152602001848152602001838152602001828103825287818151815260200191508051906020019080838360005b83811015614bca578181015183820152602001614bb2565b50505050905090810190601f168015614bf75780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b158015614c1b57600080fd5b505af1158015614c2f573d6000803e3d6000fd5b50505050614c47600184613afe90919063ffffffff16565b601255614c53856154e0565b509098975050505050505050565b600080825160208401856127105a03f43d604051816000823e828015614c85578282f35b8282fd5b60006020825181614c9657fe5b0615614ce0576040805162461bcd60e51b8152602060048201526014602482015273092dcecc2d8d2c840e0e4dedecc40d8cadccee8d60631b604482015290519081900360640190fd5b60006020835181614ced57fe5b0490508060020a8510614d3f576040805162461bcd60e51b81526020600482015260156024820152744c65616620696e64657820697320746f6f2062696760581b604482015290519081900360640190fd5b60008660205b85518111614dd15785810151925060028806614d915781836040516020018083815260200182815260200192505050604051602081830303815290604052805190602001209150614dc3565b828260405160200180838152602001828152602001925050506040516020818303038152906040528051906020012091505b600288049750602001614d45565b509094149695505050505050565b80614ded57614ded82615ac2565b6000614df882615a99565b9050806001600160a01b031663a9059cbb85856040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015614e5a57600080fd5b505af1158015614e6e573d6000803e3d6000fd5b505050506040513d6020811015614e8457600080fd5b5051611dda576040805162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b604482015290519081900360640190fd5b612a1381602454602454615c4b565b6000828152601a60205260409020600a0154614efa908263ffffffff613afe16565b6000928352601a6020526040909220600a019190915550565b6000805460ff19169055565b6000848152601a60205260408120600601546001600160a01b0316331480614fbe57506004805460408051631ab0168360e31b8152905133936001600160a01b039093169263d580b41892808201926020929091829003018186803b158015614f8757600080fd5b505afa158015614f9b573d6000803e3d6000fd5b505050506040513d6020811015614fb157600080fd5b50516001600160a01b0316145b614ffd576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b8161500b5761500b84615ac2565b600061501683615a99565b9050806001600160a01b031663a9059cbb85876040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561507857600080fd5b505af115801561508c573d6000803e3d6000fd5b505050506040513d60208110156150a257600080fd5b50519695505050505050565b6000828152601a602052604090206003015480158015906150e457506009546008546150e190839063ffffffff613afe16565b11155b8015615117575060036000848152601a6020526040902060060154600160a01b900460ff16600381111561511457fe5b14155b61512057600080fd5b6000838152601a6020526040812054601154909190615145908363ffffffff6142a916565b60118190559050615157853386615609565b60065460408051630852cd8d60e31b81526004810188905290516001600160a01b03909216916342966c689160248082019260009290919082900301818387803b1580156151a457600080fd5b505af11580156151b8573d6000803e3d6000fd5b5050506000868152601a6020526040812081815560048101919091556005810180546001600160a01b03191690556000197f584f46c60af19681376031579adb04a2416e54ee5505351c2a8435e3766026ea55600601805460ff60a01b1916600360a01b1790555061522b338386614ddf565b6005546040805163ae2e26b160e01b815233600482015260248101889052604481018590526064810184905290516001600160a01b039092169163ae2e26b19160848082019260009290919082900301818387803b15801561238457600080fd5b600080821161529a57600080fd5b60008284816152a557fe5b04949350505050565b6001600160a01b0381166152c157600080fd5b6001546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000815160401461535f576040805162461bcd60e51b81526020600482015260076024820152663737ba10383ab160c91b604482015290519081900360640190fd5b815160208301206001600160a01b0381161580159061539457506001600160a01b0381166000908152601b6020526040902054155b611db5576040805162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b604482015290519081900360640190fd5b602680549060009060001983018381106153ec57fe5b600091825260209091200154602680546001600160a01b03909216925090600019840190811061541857fe5b600091825260209091200180546001600160a01b031916905560001982015b80156154cf57836001600160a01b0316826001600160a01b0316141561545c576154cf565b6026600182038154811061546c57fe5b9060005260206000200160009054906101000a90046001600160a01b0316826026600184038154811061549b57fe5b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055915060001901615437565b506000198201611dda602682615eee565b6026805460018101825560008290527f744a2cf8fd7008e3d53b67916e73460df9fa5214e3ef23dd4259ca09493a35940180546001600160a01b0319166001600160a01b0384161790555460001901805b80156155b25760006026600183038154811061554957fe5b6000918252602090912001546001600160a01b039081169150841681101561557157506155b2565b806026838154811061557f57fe5b600091825260209091200180546001600160a01b0319166001600160a01b03929092169190911790555060001901615531565b8181146127ca5782602682815481106155c757fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6000805460ff19166001179055565b6000838152601a6020526040812060019081015461562c9163ffffffff6142a916565b601454909150615642908263ffffffff613afe16565b6014556000848152601a60205260409020600190810155615664838284614ddf565b60055460145460408051635b42d93560e11b815260048101889052602481018590526044810192909252516001600160a01b039092169163b685b26a9160648082019260009290919082900301818387803b1580156156c257600080fd5b505af11580156156d6573d6000803e3d6000fd5b5050505050505050565b60006156eb82615a99565b604080516323b872dd60e01b81526001600160a01b0388811660048301528781166024830152604482018790529151929350908316916323b872dd916064808201926020929091908290030181600087803b15801561574957600080fd5b505af115801561575d573d6000803e3d6000fd5b505050506040513d602081101561577357600080fd5b50516157bd576040805162461bcd60e51b81526020600482015260146024820152731d1c985b9cd9995c88199c9bdb4819985a5b195960621b604482015290519081900360640190fd5b811580156157d357506001600160a01b03841630145b1561251e5761251e836142be565b6000826157f057506000611db5565b828202828482816157fd57fe5b041461223157600080fd5b600e54600b54600091908261582883888161581f57fe5b04602954615d1b565b905060008111801561583c57506027548114155b1561587d57602754156158775760006064602a5484028161585957fe5b04905081602754111561586f5791820191615875565b80830392505b505b60278190555b600083881115615916576028546158c56158b560646140e66158a860026000198901890204866157e1565b889063ffffffff6157e116565b612225868663ffffffff6157e116565b91506158e76158da848763ffffffff6157e116565b8a9063ffffffff6142a916565b985061591261590560646140e6846141da898963ffffffff6157e116565b859063ffffffff6142a916565b9350505b61593a61592d856140e68b8763ffffffff6157e116565b829063ffffffff613afe16565b9050615950866140e6838a63ffffffff6157e116565b98975050505050505050565b60245460005b8381101561251e5761598885828151811061597957fe5b60200260200101518385615c4b565b600101615962565b60095460006159a682600163ffffffff613afe16565b90506159b0615f12565b506000818152601e602090815260408083208151808301909252805480835260019091015492820183905290926159e79290613b10565b506000918252601e6020526040822082815560010191909155600955565b60008082615a1857506000905080615a90565b6000615a2e846140e6888863ffffffff6157e116565b6000888152601a60205260409020600701549091508015615a7557615a72615a6560646140e6846141da8b8863ffffffff6142a916565b839063ffffffff613afe16565b91505b6000615a87878463ffffffff6142a916565b92945091925050505b94509492505050565b600081615ab157602b546001600160a01b0316611db5565b50506003546001600160a01b031690565b600354604080516370a0823160e01b8152306004820152905183926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015615b0c57600080fd5b505afa158015615b20573d6000803e3d6000fd5b505050506040513d6020811015615b3657600080fd5b50511015615b79576040805162461bcd60e51b815260206004820152600b60248201526a131858dada5b99c81413d360aa1b604482015290519081900360640190fd5b600354602c546040805163095ea7b360e01b81526001600160a01b039283166004820152602481018590529051919092169163095ea7b39160448083019260209291908290030181600087803b158015615bd257600080fd5b505af1158015615be6573d6000803e3d6000fd5b505050506040513d6020811015615bfc57600080fd5b5050602c546040805163efeff0c160e01b81526004810184905290516001600160a01b039092169163efeff0c19160248082019260009290919082900301818387803b15801561444957600080fd5b6000838152601a60205260409020600301548015801590615c6e57508060095410155b15615c7957506127ca565b6000848152601a60205260409020600b015483811015615cf8576000858152601a602052604090208054600a909101548015615ce0576000615cc1838363ffffffff613afe16565b9050615cda888484615cd58c868d8b615d31565b615d55565b50615cf5565b615cf587615cf089858a88615d31565b615dfb565b50505b8083111561251e576000858152601a60205260409020600b018390555050505050565b6000818310615d2a5781612231565b5090919050565b6000818303613fde6a084595161401484a0000006140e6838863ffffffff6157e116565b6000615d67838563ffffffff613afe16565b9050600080615d7887878686615a05565b90925090508015615db8576000878152601a6020526040902060090154615da5908263ffffffff613afe16565b6000888152601a60205260409020600901555b8115613298576000878152601a6020526040902060010154615de0908363ffffffff613afe16565b6000888152601a602052604090206001015550505050505050565b8015611cec576000828152601a6020526040902060010154615e23908263ffffffff613afe16565b6000838152601a60205260409020600101555050565b828054828255906000526020600020908101928215615e8e579160200282015b82811115615e8e57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190615e59565b50615e9a929150615f2c565b5090565b6040518060a0016040528060008152602001600081526020016060815260200160608152602001600081525090565b60405180606001604052806000815260200160608152602001600081525090565b8154818355818111156127ca576000838152602090206127ca918101908301615f50565b604051806040016040528060008152602001600081525090565b61275c91905b80821115615e9a5780546001600160a01b0319168155600101615f32565b61275c91905b80821115615e9a5760008155600101615f5656fe4f6e6c7920676f7665726e616e636520636f6e747261637420697320617574686f72697a6564a265627a7a723158202144f16fe19a38e4b93eaa1e2c04f33e2a9f779412c9defdf18d621af20c242664736f6c63430005110032", + "nonce": "0x8c", + "chainId": "0xaa36a7" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xae07c932b4a5459bd683767dde161e9fa7ad1cc9b0ac83a39f9c291bcb22b79f", + "transactionType": "CREATE", + "contractName": null, + "contractAddress": "0x19b0b3256b22116096a2ef8cafc6e832ba18a947", + "function": null, + "arguments": null, + "transaction": { + "from": "0x0724d72eb61e508d81ca701881f2248f092953bf", + "gas": "0x3b3afb", + "value": "0x0", + "input": "0x60806040526003805460ff60a81b191690553480156200001e57600080fd5b5060038054610100338102610100600160a81b0319909216919091179182905560405191046001600160a01b0316906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3620000886001600160e01b036200008e16565b620000a3565b6003805460ff60a81b1916600160a81b179055565b61349680620000b36000396000f3fe608060405234801561001057600080fd5b50600436106103c55760003560e01c80638759c234116101ff578063b6658d071161011a578063e0db556b116100ad578063e97fddc21161007c578063e97fddc2146109aa578063eaf43bb5146109c7578063f2fde38b14610a05578063f83d08ba14610a2b576103c5565b8063e0db556b14610936578063e4457a8a1461093e578063e4cd1aec14610961578063e570b78b14610987576103c5565b8063c83ec04d116100e9578063c83ec04d146108d5578063cf309012146108f8578063dd62ed3e14610900578063df5cf7231461092e576103c5565b8063b6658d071461089a578063b89b63c1146108a2578063bfb18f29146108c5578063c7b8981c146108cd576103c5565b80639b2cb5d811610192578063a9059cbb11610161578063a9059cbb146107d8578063abf59fc914610804578063b4988fd01461083a578063b60c76fa1461086e576103c5565b80639b2cb5d814610770578063a0c1ca3414610778578063a457c2d7146107a4578063a69df4b5146107d0576103c5565b80638d16a14a116101ce5780638d16a14a146107505780638da5cb5b146107585780638f32d59b146107605780639ad5f5a414610768576103c5565b80638759c2341461071b578063883b455f146107385780638ccdd289146107405780638d086da414610748576103c5565b80634f91440d116102ef5780636ab1507111610282578063715018a611610251578063715018a6146106c05780637542ff95146106c8578063795be587146106d05780637ba8c820146106fc576103c5565b80636ab15071146106225780636cbb6050146106455780636e7ce5911461066e57806370a082311461069a576103c5565b80635f0c80cc116102be5780635f0c80cc146105a35780636035083f146105ab578063653ec134146105d6578063676e5550146105fc576103c5565b80634f91440d1461056c5780635adc6dde146105745780635c42c733146105935780635c5f7dae1461059b576103c5565b806323b872dd116103675780633a09bf44116103365780633a09bf44146105305780633ba0b9a9146105385780633d94eb0514610540578063446a2ec814610564576103c5565b806323b872dd146104a05780633046c204146104d657806339509351146104fc57806339c31e9314610528576103c5565b80631bf494a7116103a35780631bf494a7146104495780631e7ff8f614610451578063232e5415146104905780632344067914610498576103c5565b8063029d3040146103ca578063095ea7b3146103ef57806318160ddd1461042f575b600080fd5b6103ed600480360360408110156103e057600080fd5b5080359060200135610a33565b005b61041b6004803603604081101561040557600080fd5b506001600160a01b038135169060200135610a43565b604080519115158252519081900360200190f35b610437610a5a565b60408051918252519081900360200190f35b610437610a61565b6104776004803603602081101561046757600080fd5b50356001600160a01b0316610aed565b6040805192835260208301919091528051918290030190f35b6103ed610b4d565b610437610b59565b61041b600480360360608110156104b657600080fd5b506001600160a01b03813581169160208101359091169060400135610b5f565b610437600480360360208110156104ec57600080fd5b50356001600160a01b0316610bb7565b61041b6004803603604081101561051257600080fd5b506001600160a01b038135169060200135610bc9565b610437610c05565b610437610c0b565b610437610c11565b610548610cce565b604080516001600160a01b039092168252519081900360200190f35b610437610cdd565b610477610ce3565b6104776004803603602081101561058a57600080fd5b50351515610cf8565b610437610ff1565b610437610ff7565b610437610ffd565b6103ed600480360360608110156105c157600080fd5b50803590602081013590604001351515611003565b610477600480360360208110156105ec57600080fd5b50356001600160a01b03166111fe565b6104376004803603602081101561061257600080fd5b50356001600160a01b0316611217565b6104376004803603604081101561063857600080fd5b508035906020013561122a565b6104376004803603606081101561065b57600080fd5b5080359060208101359060400135611238565b6103ed6004803603604081101561068457600080fd5b506001600160a01b03813516906020013561136f565b610437600480360360208110156106b057600080fd5b50356001600160a01b03166115fb565b6103ed611616565b610548611677565b610477600480360360408110156106e657600080fd5b506001600160a01b038135169060200135611686565b6103ed6004803603602081101561071257600080fd5b503515156116aa565b6103ed6004803603602081101561073157600080fd5b50356116ce565b6105486116dc565b6104376116eb565b6104376116f1565b6103ed6116f7565b610548611701565b61041b611715565b61047761172b565b610437611738565b6103ed6004803603604081101561078e57600080fd5b506001600160a01b03813516906020013561173e565b61041b600480360360408110156107ba57600080fd5b506001600160a01b03813516906020013561176c565b6103ed6117a8565b61041b600480360360408110156107ee57600080fd5b506001600160a01b0381351690602001356117c1565b6103ed6004803603606081101561081a57600080fd5b506001600160a01b038135811691602081013590911690604001356117cf565b6103ed6004803603606081101561085057600080fd5b508035906001600160a01b03602082013581169160400135166118f6565b61041b6004803603604081101561088457600080fd5b506001600160a01b0381351690602001356119be565b6105486119cc565b6103ed600480360360408110156108b857600080fd5b50803590602001356119db565b6104376119e7565b6103ed611a2e565b6103ed600480360360408110156108eb57600080fd5b5080359060200135611a38565b61041b611a44565b6104376004803603604081101561091657600080fd5b506001600160a01b0381358116916020013516611a4d565b61041b611a78565b6103ed611a81565b6104376004803603604081101561095457600080fd5b5080359060200135611a8b565b6104376004803603602081101561097757600080fd5b50356001600160a01b0316611a99565b6103ed6004803603604081101561099d57600080fd5b5080359060200135611aab565b6103ed600480360360208110156109c057600080fd5b5035611ab7565b610437600480360360c08110156109dd57600080fd5b5080359060208101359060408101359060ff6060820135169060808101359060a00135611ac2565b6103ed60048036036020811015610a1b57600080fd5b50356001600160a01b0316611cab565b6103ed611cc5565b610a3f82826000611cde565b5050565b6000610a50338484611e8e565b5060015b92915050565b6002545b90565b6005546006546040805163072c21ef60e31b8152600481019290925251600092610ae8926001600160a01b03909116916339610f7891602480820192602092909190829003018186803b158015610ab757600080fd5b505afa158015610acb573d6000803e3d6000fd5b505050506040513d6020811015610ae157600080fd5b5051611ec6565b905090565b6000806000610afb846115fb565b90506000610b07610c11565b905081610b1b57600093509150610b489050565b610b42610b26611f1d565b610b36838563ffffffff611f4416565b9063ffffffff611f6b16565b93509150505b915091565b610b576001611f8d565b565b60095481565b6000610b6c84848461205a565b6001600160a01b038416600090815260016020908152604080832033808552925290912054610bac918691610ba7908663ffffffff61212516565b611e8e565b5060015b9392505050565b60146020526000908152604090205481565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091610a50918590610ba7908663ffffffff61213a16565b60075481565b600d5481565b600080610c1c610a5a565b90506000610c28611f1d565b90508115610cc55760055460065460408051637f4b432360e01b8152600481019290925251610cc0928592610b369286926001600160a01b031691637f4b4323916024808301926020929190829003018186803b158015610c8857600080fd5b505afa158015610c9c573d6000803e3d6000fd5b505050506040513d6020811015610cb257600080fd5b50519063ffffffff611f4416565b610cc7565b805b9250505090565b6004546001600160a01b031681565b600c5481565b600080610cf06000610cf8565b915091509091565b6000803381610d068261214c565b90506000600a54821015610d61576040805162461bcd60e51b815260206004820152601c60248201527f546f6f20736d616c6c207265776172647320746f2072657374616b6500000000604482015290519081900360640190fd5b8115610b4257610d73826000856121fa565b905080821115610f615785610e14576005546006546040805163bc8756a960e01b8152600481019290925283850360248301526001600160a01b038681166044840152905192169163bc8756a9916064808201926020929091908290030181600087803b158015610de357600080fd5b505af1158015610df7573d6000803e3d6000fd5b505050506040513d6020811015610e0d57600080fd5b5051610ea2565b6005546006546040805163c7f067cb60e01b8152600481019290925283850360248301526001600160a01b038681166044840152905192169163c7f067cb916064808201926020929091908290030181600087803b158015610e7557600080fd5b505af1158015610e89573d6000803e3d6000fd5b505050506040513d6020811015610e9f57600080fd5b50515b610ee9576040805162461bcd60e51b8152602060048201526013602482015272496e737566666963656e74207265776172647360681b604482015290519081900360640190fd5b600480546006546040805163b7721d2d60e01b8152938401919091526001600160a01b0386811660248501528486036044850152905191169163b7721d2d91606480830192600092919082900301818387803b158015610f4857600080fd5b505af1158015610f5c573d6000803e3d6000fd5b505050505b6000610f6c84610aed565b506004805460065460408051637f88a95760e01b8152938401919091526001600160a01b0388811660248501526044840185905290519394501691637f88a9579160648082019260009290919082900301818387803b158015610fce57600080fd5b505af1158015610fe2573d6000803e3d6000fd5b50505050509350915050915091565b600f5481565b60065481565b600b5481565b6000806110118585856124b9565b336000908152601460205260408120549294509092509061103990600163ffffffff61213a16565b9050611043613447565b6040518060400160405280848152602001600560009054906101000a90046001600160a01b03166001600160a01b031663900cf0cf6040518163ffffffff1660e01b815260040160206040518083038186803b1580156110a257600080fd5b505afa1580156110b6573d6000803e3d6000fd5b505050506040513d60208110156110cc57600080fd5b50519052336000818152601560209081526040808320878452825280832085518155858301516001909101559282526014905220839055905061110d612685565b60065460408051632a9b5b4160e11b81526004810192909252336024830152604482018a90526064820187905260848201859052516001600160a01b039290921691635536b6829160a48082019260009290919082900301818387803b15801561117657600080fd5b505af115801561118a573d6000803e3d6000fd5b5050600480546006546040805163532e19a960e01b815293840191909152516001600160a01b03909116935063532e19a99250602480830192600092919082900301818387803b1580156111dd57600080fd5b505af11580156111f1573d6000803e3d6000fd5b5050505050505050505050565b6012602052600090815260409020805460019091015482565b6000610a5482611225610a61565b6127c2565b6000610bb083836000612843565b6000611242611715565b61124b57600080fd5b600f546000611260858363ffffffff61213a16565b90508061127257600092505050610bb0565b6000611297611287888463ffffffff61213a16565b610b36848863ffffffff611f4416565b905060006112af83610b36868563ffffffff611f4416565b905060006112c3838363ffffffff61212516565b6005546006546040805163858a7c0360e01b8152600481019290925260248201849052519293506001600160a01b039091169163858a7c039160448082019260009290919082900301818387803b15801561131d57600080fd5b505af1158015611331573d6000803e3d6000fd5b5050600d54611349925090508263ffffffff61212516565b600d55600f5461135f908363ffffffff61212516565b600f555090979650505050505050565b611377611715565b61138057600080fd5b61138b8260016129bd565b5060008061139884610aed565b91509150828210156113e6576040805162461bcd60e51b815260206004820152601260248201527109ad2cee4c2e8d2dcce40e8dede40daeac6d60731b604482015290519081900360640190fd5b60006113f0611f1d565b9050600061140883610b36878563ffffffff611f4416565b90506114148682612bb9565b60055460065460408051629ff11560e81b815260048101929092526000888103602484015290516001600160a01b0390931692639ff1150092604480820193929182900301818387803b15801561146a57600080fd5b505af115801561147e573d6000803e3d6000fd5b5050600d54611496925090508663ffffffff61212516565b600d55600480546006546040805163f1382b5360e01b8152938401919091526001600160a01b0389811660248501526044840189905260648401859052905191169163f1382b5391608480830192600092919082900301818387803b1580156114fe57600080fd5b505af1158015611512573d6000803e3d6000fd5b5050600480546006546040805163532e19a960e01b815293840191909152516001600160a01b03909116935063532e19a99250602480830192600092919082900301818387803b15801561156557600080fd5b505af1158015611579573d6000803e3d6000fd5b5050600480546006546040805163302df4df60e11b8152938401919091526001600160a01b038b81166024850152604484018b905290519116935063605be9be9250606480830192600092919082900301818387803b1580156115db57600080fd5b505af11580156115ef573d6000803e3d6000fd5b50505050505050505050565b6001600160a01b031660009081526020819052604090205490565b61161e611715565b61162757600080fd5b60035460405160009161010090046001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a360038054610100600160a81b0319169055565b6005546001600160a01b031681565b60156020908152600092835260408084209091529082529020805460019091015482565b6116b2611715565b6116bb57600080fd5b600e805460ff1916911515919091179055565b6116d9816001612c60565b50565b6016546001600160a01b031681565b60085481565b60105481565b610b576000611f8d565b60035461010090046001600160a01b031690565b60035461010090046001600160a01b0316331490565b600080610cf06001610cf8565b600a5481565b611746611715565b61174f57600080fd5b61175a8260016129bd565b50611767816000846121fa565b505050565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091610a50918590610ba7908663ffffffff61212516565b6117b0611715565b6117b957600080fd5b610b57612d50565b6000610a5083836000612d5c565b6117d7611715565b6117e057600080fd5b6001600160a01b03831661182a576040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015611824573d6000803e3d6000fd5b50611767565b826001600160a01b031663a9059cbb83836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561188a57600080fd5b505af115801561189e573d6000803e3d6000fd5b505050506040513d60208110156118b457600080fd5b5051611767576040805162461bcd60e51b815260206004820152600c60248201526b111c985a5b8819985a5b195960a21b604482015290519081900360640190fd5b600354600160a81b900460ff1615611946576040805162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481a5b9a5d195960921b604482015290519081900360640190fd5b6003805460ff60a81b1916600160a81b1790556006839055600480546001600160a01b038085166001600160a01b031992831617909255600580549284169290911691909117905561199781612dea565b61199f612685565b5050670de0b6b3a7640000600a555050600e805460ff19166001179055565b6000610a5083836001612d5c565b6017546001600160a01b031681565b610a3f82826001611cde565b6000806119f2611f1d565b905060086006541015611a06579050610a5e565b6010548015611a2857610cc081610b3684600f54611f4490919063ffffffff16565b50919050565b610b576000612e64565b610a3f82826000611003565b60035460ff1681565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600e5460ff1681565b610b576001612e64565b6000610bb083836001612843565b60136020526000908152604090205481565b610a3f82826001611003565b6116d9816000612c60565b600080611acd612ec9565b60408051623f675f60e91b815233600482015290519192506000916001600160a01b03841691637ecebe00916024808301926020929190829003018186803b158015611b1857600080fd5b505afa158015611b2c573d6000803e3d6000fd5b505050506040513d6020811015611b4257600080fd5b50516005546040805163d505accf60e01b81523360048201526001600160a01b039283166024820152604481018d9052606481018b905260ff8a16608482015260a4810189905260c4810188905290519293509084169163d505accf9160e48082019260009290919082900301818387803b158015611bc057600080fd5b505af1158015611bd4573d6000803e3d6000fd5b505060408051623f675f60e91b815233600482015290516001850193506001600160a01b0386169250637ecebe0091602480820192602092909190829003018186803b158015611c2357600080fd5b505afa158015611c37573d6000803e3d6000fd5b505050506040513d6020811015611c4d57600080fd5b505114611c92576040805162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a59081c195c9b5a5d60921b604482015290519081900360640190fd5b611c9e89896001612843565b9998505050505050505050565b611cb3611715565b611cbc57600080fd5b6116d981612dea565b611ccd611715565b611cd657600080fd5b610b57613043565b600080611cec8585856124b9565b91509150611cf8613447565b50336000908152601260209081526040918290208251808401909352805480845260019091015491830191909152611d36908363ffffffff61213a16565b81526005546040805163900cf0cf60e01b815290516001600160a01b039092169163900cf0cf91600480820192602092909190829003018186803b158015611d7d57600080fd5b505afa158015611d91573d6000803e3d6000fd5b505050506040513d6020811015611da757600080fd5b505160208281019182523360008181526012909252604080832085518155935160019094019390935560048054600654855163f1382b5360e01b8152928301526024820192909252604481018a90526064810187905292516001600160a01b0390911692839263f1382b539260848084019382900301818387803b158015611e2e57600080fd5b505af1158015611e42573d6000803e3d6000fd5b50505050806001600160a01b031663532e19a96006546040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156111dd57600080fd5b6040805162461bcd60e51b8152602060048201526008602482015267191a5cd8589b195960c21b604482015290519081900360640190fd5b600c546000908215610a54576000611edc610a5a565b90508015611f1657611f13611f0682610b36876a084595161401484a00000063ffffffff611f4416565b839063ffffffff61213a16565b91505b5092915050565b600060086006541015611f3257506064610a5e565b506c01431e0fae6d7217caa000000090565b600082611f5357506000610a54565b82820282848281611f6057fe5b0414610bb057600080fd5b6000808211611f7957600080fd5b6000828481611f8457fe5b04949350505050565b611f95613447565b50336000908152601260209081526040808320815180830190925280548252600101549181019190915290611fca8284613052565b3360008181526012602052604080822082815560010182905560048054600654835163302df4df60e11b81529283015260248201949094526044810185905290519394506001600160a01b039092169263605be9be92606480820193929182900301818387803b15801561203d57600080fd5b505af1158015612051573d6000803e3d6000fd5b50505050505050565b6001600160a01b03821661206d57600080fd5b6001600160a01b038316600090815260208190526040902054612096908263ffffffff61212516565b6001600160a01b0380851660009081526020819052604080822093909355908416815220546120cb908263ffffffff61213a16565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008282111561213457600080fd5b50900390565b600082820183811015610bb057600080fd5b6000806121c3600560009054906101000a90046001600160a01b03166001600160a01b0316637ed4b27c6006546040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b1580156121af57600080fd5b505af1158015610acb573d6000803e3d6000fd5b905060006121d184836127c2565b600c8390556001600160a01b038516600090815260136020526040902092909255509050919050565b600061220461335e565b600e5460ff16612254576040805162461bcd60e51b815260206004820152601660248201527511195b1959d85d1a5bdb881a5cc8191a5cd8589b195960521b604482015290519081900360640190fd5b600061225e610c11565b9050600061226a611f1d565b9050600061228283610b36898563ffffffff611f4416565b9050858110156122cd576040805162461bcd60e51b8152602060048201526011602482015270546f6f206d75636820736c69707061676560781b604482015290519081900360640190fd5b6001600160a01b03851660009081526012602052604090205415612327576040805162461bcd60e51b815260206004820152600c60248201526b13db99dbda5b99c8195e1a5d60a21b604482015290519081900360640190fd5b612331858261339f565b61234582610b36858463ffffffff611f4416565b60055460065460408051629ff11560e81b8152600481019290925260248201849052519299506001600160a01b0390911691639ff115009160448082019260009290919082900301818387803b15801561239e57600080fd5b505af11580156123b2573d6000803e3d6000fd5b5050600d546123ca925090508863ffffffff61213a16565b600d55600480546006546040805163c69d057360e01b8152938401919091526001600160a01b038881166024850152604484018b9052606484018590529051911691829163c69d05739160848082019260009290919082900301818387803b15801561243557600080fd5b505af1158015612449573d6000803e3d6000fd5b50505050806001600160a01b031663532e19a96006546040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561249557600080fd5b505af11580156124a9573d6000803e3d6000fd5b50999a9950505050505050505050565b6000806000806124c833610aed565b91509150816000141580156124dd5750868210155b612523576040805162461bcd60e51b8152602060048201526012602482015271151bdbc81b5d58da081c995c5d595cdd195960721b604482015290519081900360640190fd5b600061252d611f1d565b9050600061254583610b368b8563ffffffff611f4416565b905087811115612590576040805162461bcd60e51b8152602060048201526011602482015270746f6f206d75636820736c69707061676560781b604482015290519081900360640190fd5b61259a33886129bd565b506125a53382612bb9565b60055460065460408051629ff11560e81b8152600481019290925260008c8103602484015290516001600160a01b0390931692639ff1150092604480820193929182900301818387803b1580156125fb57600080fd5b505af115801561260f573d6000803e3d6000fd5b5050600d54612627925090508a63ffffffff61212516565b600d5560006126476126376119e7565b610b368c8663ffffffff611f4416565b600f5490915061265d908b63ffffffff61213a16565b600f55601054612673908263ffffffff61213a16565b60105590999098509650505050505050565b6016546000906001600160a01b031680610ae857600560009054906101000a90046001600160a01b03166001600160a01b0316635ab1bd536040518163ffffffff1660e01b815260040160206040518083038186803b1580156126e757600080fd5b505afa1580156126fb573d6000803e3d6000fd5b505050506040513d602081101561271157600080fd5b5051604080516832bb32b73a39a43ab160b91b8152815190819003600901812063cac39a0560e01b8252600482015290516001600160a01b039092169163cac39a0591602480820192602092909190829003018186803b15801561277457600080fd5b505afa158015612788573d6000803e3d6000fd5b505050506040513d602081101561279e57600080fd5b5051601680546001600160a01b0319166001600160a01b0383161790559050905090565b6000806127ce846115fb565b9050806127df576000915050610a54565b6001600160a01b0384166000908152601360205260409020548381141561280b57600092505050610a54565b61283a6a084595161401484a000000610b368461282e888663ffffffff61212516565b9063ffffffff611f4416565b95945050505050565b600061284f33836129bd565b5061285b8484336121fa565b9050816128f15760055460065460408051636901b25360e01b8152600481019290925260248201849052336044830152516001600160a01b0390921691636901b253916064808201926020929091908290030181600087803b1580156128c057600080fd5b505af11580156128d4573d6000803e3d6000fd5b505050506040513d60208110156128ea57600080fd5b505161297b565b60055460065460408051624c025560e81b8152600481019290925260248201849052336044830152516001600160a01b0390921691634c025500916064808201926020929091908290030181600087803b15801561294e57600080fd5b505af1158015612962573d6000803e3d6000fd5b505050506040513d602081101561297857600080fd5b50515b610bb0576040805162461bcd60e51b815260206004820152600e60248201526d19195c1bdcda5d0819985a5b195960921b604482015290519081900360640190fd5b6000806129c98461214c565b90508015610bb05782612a67576005546006546040805163bc8756a960e01b81526004810192909252602482018490526001600160a01b038781166044840152905192169163bc8756a9916064808201926020929091908290030181600087803b158015612a3657600080fd5b505af1158015612a4a573d6000803e3d6000fd5b505050506040513d6020811015612a6057600080fd5b5051612af4565b6005546006546040805163c7f067cb60e01b81526004810192909252602482018490526001600160a01b038781166044840152905192169163c7f067cb916064808201926020929091908290030181600087803b158015612ac757600080fd5b505af1158015612adb573d6000803e3d6000fd5b505050506040513d6020811015612af157600080fd5b50515b612b3b576040805162461bcd60e51b8152602060048201526013602482015272496e737566666963656e74207265776172647360681b604482015290519081900360640190fd5b600480546006546040805163b7721d2d60e01b8152938401919091526001600160a01b03878116602485015260448401859052905191169163b7721d2d91606480830192600092919082900301818387803b158015612b9957600080fd5b505af1158015612bad573d6000803e3d6000fd5b50505050905092915050565b6001600160a01b038216612bcc57600080fd5b600254612bdf908263ffffffff61212516565b6002556001600160a01b038216600090815260208190526040902054612c0b908263ffffffff61212516565b6001600160a01b038316600081815260208181526040808320949094558351858152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35050565b612c68613447565b503360009081526015602090815260408083208584528252808320815180830190925280548252600101549181019190915290612ca58284613052565b3360009081526015602090815260408083208884529091528120818155600101559050612cd0612685565b60065460408051636e699d8760e01b815260048101929092523360248301526044820184905260648201879052516001600160a01b039290921691636e699d879160848082019260009290919082900301818387803b158015612d3257600080fd5b505af1158015612d46573d6000803e3d6000fd5b5050505050505050565b6003805460ff19169055565b33612d6784836129bd565b50612d7281836129bd565b50612d7e81858561205a565b612d86612685565b6006546040805163c08b3f9d60e01b815260048101929092526001600160a01b038481166024840152878116604484015260648301879052905192169163c08b3f9d9160848082019260009290919082900301818387803b158015612d3257600080fd5b6001600160a01b038116612dfd57600080fd5b6003546040516001600160a01b0380841692610100900416907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6000612e7033836129bd565b9050600a54811015610a3f576040805162461bcd60e51b815260206004820152601860248201527f546f6f20736d616c6c207265776172647320616d6f756e740000000000000000604482015290519081900360640190fd5b6017546000906001600160a01b031680610ae857600560009054906101000a90046001600160a01b03166001600160a01b0316635ab1bd536040518163ffffffff1660e01b815260040160206040518083038186803b158015612f2b57600080fd5b505afa158015612f3f573d6000803e3d6000fd5b505050506040513d6020811015612f5557600080fd5b505160408051621c1bdb60ea1b8152815190819003600301812063cac39a0560e01b8252600482015290516001600160a01b039092169163cac39a0591602480820192602092909190829003018186803b158015612fb257600080fd5b505afa158015612fc6573d6000803e3d6000fd5b505050506040513d6020811015612fdc57600080fd5b505190506001600160a01b038116613023576040805162461bcd60e51b81526020600482015260056024820152641d5b9cd95d60da1b604482015290519081900360640190fd5b601780546001600160a01b0319166001600160a01b038316179055919050565b6003805460ff19166001179055565b81516005546040805163900cf0cf60e01b81529051600093926001600160a01b03169163900cf0cf916004808301926020929190829003018186803b15801561309a57600080fd5b505afa1580156130ae573d6000803e3d6000fd5b505050506040513d60208110156130c457600080fd5b50516005546040805163a7ab696160e01b81529051613149926001600160a01b03169163a7ab6961916004808301926020929190829003018186803b15801561310c57600080fd5b505afa158015613120573d6000803e3d6000fd5b505050506040513d602081101561313657600080fd5b505160208701519063ffffffff61213a16565b111580156131575750600081115b6131a8576040805162461bcd60e51b815260206004820152601c60248201527f496e636f6d706c657465207769746864726177616c20706572696f6400000000604482015290519081900360640190fd5b60006131c16131b5611f1d565b610b368461282e6119e7565b6010549091506131d7908363ffffffff61212516565b601055600f546131ed908263ffffffff61212516565b600f5583613284576005546006546040805163bc8756a960e01b8152600481019290925260248201849052336044830152516001600160a01b039092169163bc8756a9916064808201926020929091908290030181600087803b15801561325357600080fd5b505af1158015613267573d6000803e3d6000fd5b505050506040513d602081101561327d57600080fd5b505161330f565b6005546006546040805163c7f067cb60e01b8152600481019290925260248201849052336044830152516001600160a01b039092169163c7f067cb916064808201926020929091908290030181600087803b1580156132e257600080fd5b505af11580156132f6573d6000803e3d6000fd5b505050506040513d602081101561330c57600080fd5b50515b613356576040805162461bcd60e51b8152602060048201526013602482015272496e737566666963656e74207265776172647360681b604482015290519081900360640190fd5b949350505050565b60035460ff1615610b57576040805162461bcd60e51b81526020600482015260066024820152651b1bd8dad95960d21b604482015290519081900360640190fd5b6001600160a01b0382166133b257600080fd5b6002546133c5908263ffffffff61213a16565b6002556001600160a01b0382166000908152602081905260409020546133f1908263ffffffff61213a16565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b60405180604001604052806000815260200160008152509056fea265627a7a723158204218c2c8b2e87f177283c78647790865bea3a76c3c8e35d83898fc32476d052564736f6c63430005110032", + "nonce": "0x8d", + "chainId": "0xaa36a7" + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "status": "0x1", + "cumulativeGasUsed": "0xcf4a40", + "logs": [ + { + "address": "0x777badc2c75bd4ee5303bf6e90009bd31d8fd3d1", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000724d72eb61e508d81ca701881f2248f092953bf" + ], + "data": "0x", + "blockHash": "0x80bb5b7121caad8c640dafc4e50623df1bc4757fbe8f5cd035bd702d975119ec", + "blockNumber": "0x605f17", + "transactionHash": "0x4499d0ecf70c3a39927d5245cac653c02f0f0c33dc82be6a9ce5d37d4615c70a", + "transactionIndex": "0x40", + "logIndex": "0x73", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000002000001000000000000004000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000020000010000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x4499d0ecf70c3a39927d5245cac653c02f0f0c33dc82be6a9ce5d37d4615c70a", + "transactionIndex": "0x40", + "blockHash": "0x80bb5b7121caad8c640dafc4e50623df1bc4757fbe8f5cd035bd702d975119ec", + "blockNumber": "0x605f17", + "gasUsed": "0x526898", + "effectiveGasPrice": "0x3be653915", + "from": "0x0724d72eb61e508d81ca701881f2248f092953bf", + "to": null, + "contractAddress": "0x777badc2c75bd4ee5303bf6e90009bd31d8fd3d1" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xfcdd6b", + "logs": [ + { + "address": "0x19b0b3256b22116096a2ef8cafc6e832ba18a947", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000724d72eb61e508d81ca701881f2248f092953bf" + ], + "data": "0x", + "blockHash": "0x80bb5b7121caad8c640dafc4e50623df1bc4757fbe8f5cd035bd702d975119ec", + "blockNumber": "0x605f17", + "transactionHash": "0xae07c932b4a5459bd683767dde161e9fa7ad1cc9b0ac83a39f9c291bcb22b79f", + "transactionIndex": "0x41", + "logIndex": "0x74", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000100100400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000020000010000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xae07c932b4a5459bd683767dde161e9fa7ad1cc9b0ac83a39f9c291bcb22b79f", + "transactionIndex": "0x41", + "blockHash": "0x80bb5b7121caad8c640dafc4e50623df1bc4757fbe8f5cd035bd702d975119ec", + "blockNumber": "0x605f17", + "gasUsed": "0x2d932b", + "effectiveGasPrice": "0x3be653915", + "from": "0x0724d72eb61e508d81ca701881f2248f092953bf", + "to": null, + "contractAddress": "0x19b0b3256b22116096a2ef8cafc6e832ba18a947" + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1721057742, + "chain": 11155111, + "commit": "a5fd7d69" +} \ No newline at end of file diff --git a/broadcast/UpgradeStakeManager_Sepolia.s.sol/11155111/run-latest.json b/broadcast/UpgradeStakeManager_Sepolia.s.sol/11155111/run-latest.json new file mode 100644 index 00000000..eceb3423 --- /dev/null +++ b/broadcast/UpgradeStakeManager_Sepolia.s.sol/11155111/run-latest.json @@ -0,0 +1,112 @@ +{ + "transactions": [ + { + "hash": "0x4499d0ecf70c3a39927d5245cac653c02f0f0c33dc82be6a9ce5d37d4615c70a", + "transactionType": "CREATE", + "contractName": null, + "contractAddress": "0x777badc2c75bd4ee5303bf6e90009bd31d8fd3d1", + "function": null, + "arguments": null, + "transaction": { + "from": "0x0724d72eb61e508d81ca701881f2248f092953bf", + "gas": "0x6b19b6", + "value": "0x0", + "input": "0x60806040526023805460ff191690553480156200001b57600080fd5b5060008054610100600160a81b0319168155600180546001600160a01b0319163317908190556040516001600160a01b039190911691907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a360235460ff1615620000c1576040805162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481a5b9a5d195960921b604482015290519081900360640190fd5b6023805460ff19166001179055615fc580620000de6000396000f3fe608060405234801561001057600080fd5b50600436106107175760003560e01c80637d669752116103a8578063b1d23f02116101f4578063e8afa8e81161011a578063f5e95acb116100b8578063fb1ef52c11610087578063fb1ef52c14611826578063fba58f341461184f578063fc0c546a14611857578063ff3db8e31461185f57610717565b8063f5e95acb1461178f578063f771fc87146117f9578063f83d08ba14611816578063f8a3176c1461181e57610717565b8063f24ccbfe116100f4578063f24ccbfe14611697578063f28699fa1461169f578063f2fde38b146116be578063f41a9642146116e457610717565b8063e8afa8e81461164c578063eceec1d314611672578063f1674fdf1461168f57610717565b8063cf30901211610192578063dcd962b211610161578063dcd962b2146115fc578063e568959a1461161f578063e59ee0c614611627578063e6692f491461162f57610717565b8063cf3090121461159b578063d6de07d0146115a3578063d7f5549d146115c2578063d86d53e7146115df57610717565b8063c710e922116101ce578063c710e92214611518578063c7f067cb14611544578063cbf383d514611576578063cd6b83881461159357610717565b8063b1d23f02146114a6578063b65de35e146114c9578063bc8756a9146114e657610717565b80639342c8f4116102d95780639ff1150011610277578063a69df4b511610246578063a69df4b514611462578063a7ab69611461146a578063a8dc889b14611472578063b184be811461147a57610717565b80639ff1150014611397578063a440ab1e146113ba578063a4769071146113d7578063a6854877146113df57610717565b806399d18f6f116102b357806399d18f6f1461132c5780639a8a62431461134f5780639b33f434146113575780639ddbbf851461137457610717565b80639342c8f4146112dc57806396a93224146112f9578063987ab9db1461132457610717565b806386a22666116103465780638f32d59b116103205780638f32d59b146112a7578063900cf0cf146112af57806391460149146112b757806391f1a3a5146112d457610717565b806386a226661461127a578063883b455f146112975780638da5cb5b1461129f57610717565b80637f952d95116103825780637f952d951461118057806381254e1214611188578063817b1cd21461124f578063858a7c031461125757610717565b80637d6697521461113e5780637ed4b27c146111465780637f4b43231461116357610717565b806341b3d185116105675780635ab1bd53116104985780637060054d116104365780637854f354116104055780637854f354146110eb57806378f84a44146111085780637b1039991461112e5780637c7eaf1a1461113657610717565b80637060054d146110cb578063715018a6146110d357806376671808146110db57806377939d10146110e357610717565b80636352211e116104725780636352211e14610fa05780636365679814610fbd57806368cb812a14610fe95780636901b2531461109957610717565b80635ab1bd5314610f015780635e47655f14610f0957806360c8d12214610f7757610717565b80634fdd20f11161050557806354b8c601116104df57806354b8c60114610ecc5780635508d8e114610ed457806356342d8c14610edc5780635aa6e67514610ef957610717565b80634fdd20f114610ca657806352b8115d14610d6d5780635325e14414610e0557610717565b80634b341aed116105415780634b341aed14610c3e5780634c02550014610c645780634e3c83f114610c965780634fd101d714610c9e57610717565b806341b3d18514610bf2578063451b598514610bfa57806348ab8b2a14610c0257610717565b80632079fb9a1161064c5780632fa9d18b116105ea57806335aa2e44116105b957806335aa2e4414610ac85780633862da0b14610b8157806339610f7814610ba75780633c34355614610bc457610717565b80632fa9d18b14610a0c57806330cbe57114610a9b57806331c2273b14610ab85780633427458614610ac057610717565b80632649263a116106265780632649263a146108f257806328cc4e41146109235780632cf44a431461094e5780632e17de78146109ef57610717565b80632079fb9a1461089757806325316411146108b457806325726df2146108bc57610717565b8063174e6832116106b95780631ae4818f116106935780631ae4818f1461082f5780631c404cec146108375780631dd6b9b1146108545780631e9b12ef1461087157610717565b8063174e6832146107e4578063178c2c831461080a57806317c2b9101461082757610717565b80630e15561a116106f55780630e15561a146107935780630ebb172a1461079b57806316827b1b146107a35780631705a3bd146107c057610717565b806306cfb1041461071c578063078a13b11461073b5780630cccfc5814610779575b600080fd5b6107396004803603602081101561073257600080fd5b503561187c565b005b6107396004803603608081101561075157600080fd5b506001600160a01b038135811691602081013582169160408201358116916060013516611889565b610781611901565b60408051918252519081900360200190f35b610781611907565b61078161190d565b610739600480360360208110156107b957600080fd5b5035611913565b6107c861199c565b604080516001600160a01b039092168252519081900360200190f35b610781600480360360208110156107fa57600080fd5b50356001600160a01b03166119ab565b6107396004803603602081101561082057600080fd5b5035611a35565b610781611cc2565b6107c8611cc8565b6107396004803603602081101561084d57600080fd5b5035611cd7565b6107396004803603602081101561086a57600080fd5b5035611cf0565b6107396004803603602081101561088757600080fd5b50356001600160a01b0316611cfd565b6107c8600480360360208110156108ad57600080fd5b5035611d3a565b610781611d61565b6108d9600480360360208110156108d257600080fd5b5035611d67565b6040805192835260208301919091528051918290030190f35b61090f6004803603602081101561090857600080fd5b5035611d80565b604080519115158252519081900360200190f35b6107396004803603606081101561093957600080fd5b50803590602081013590604001351515611dbb565b6107396004803603602081101561096457600080fd5b810190602081018135600160201b81111561097e57600080fd5b82018360208201111561099057600080fd5b803590602001918460208302840111600160201b831117156109b157600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550611de0945050505050565b61073960048036036020811015610a0557600080fd5b5035611e04565b610781600480360360a0811015610a2257600080fd5b8135916020810135916040820135916001600160a01b036060820135169181019060a081016080820135600160201b811115610a5d57600080fd5b820183602082011115610a6f57600080fd5b803590602001918460608302840111600160201b83111715610a9057600080fd5b509092509050611e19565b61073960048036036020811015610ab157600080fd5b503561212a565b6107c861213f565b61078161214e565b610ae560048036036020811015610ade57600080fd5b5035612154565b604051808e81526020018d81526020018c81526020018b81526020018a8152602001896001600160a01b03166001600160a01b03168152602001886001600160a01b03166001600160a01b03168152602001876003811115610b4357fe5b60ff1681526020018681526020018581526020018481526020018381526020018281526020019d505050505050505050505050505060405180910390f35b61078160048036036020811015610b9757600080fd5b50356001600160a01b03166121c5565b61078160048036036020811015610bbd57600080fd5b50356121d7565b61073960048036036040811015610bda57600080fd5b506001600160a01b0381358116916020013516612238565b6107816122f1565b6107816122f7565b61073960048036036080811015610c1857600080fd5b508035906001600160a01b036020820135811691604081013590911690606001356122fd565b61078160048036036020811015610c5457600080fd5b50356001600160a01b03166123a3565b61090f60048036036060811015610c7a57600080fd5b50803590602081013590604001356001600160a01b03166124da565b6107816124fb565b610781612501565b610739600480360360a0811015610cbc57600080fd5b6001600160a01b0382351691602081013591604082013591606081013515159181019060a081016080820135600160201b811115610cf957600080fd5b820183602082011115610d0b57600080fd5b803590602001918460018302840111600160201b83111715610d2c57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612507945050505050565b610739600480360360c0811015610d8357600080fd5b6001600160a01b038235169160208101359160408201359160608101359160808201351515919081019060c0810160a0820135600160201b811115610dc757600080fd5b820183602082011115610dd957600080fd5b803590602001918460018302840111600160201b83111715610dfa57600080fd5b509092509050612525565b610e2260048036036020811015610e1b57600080fd5b5035612648565b60405180868152602001858152602001846001600160a01b03166001600160a01b031681526020018315151515815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610e8d578181015183820152602001610e75565b50505050905090810190601f168015610eba5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b61090f61270e565b610781612717565b6107c860048036036020811015610ef257600080fd5b503561271d565b6107c861273b565b6107c861274f565b61078160048036036020811015610f1f57600080fd5b810190602081018135600160201b811115610f3957600080fd5b820183602082011115610f4b57600080fd5b803590602001918460018302840111600160201b83111715610f6c57600080fd5b50909250905061275f565b61073960048036036060811015610f8d57600080fd5b5080359060208101359060400135612766565b6107c860048036036020811015610fb657600080fd5b50356127cf565b61073960048036036040811015610fd357600080fd5b506001600160a01b03813516906020013561281b565b61073960048036036060811015610fff57600080fd5b813591602081013591810190606081016040820135600160201b81111561102557600080fd5b82018360208201111561103757600080fd5b803590602001918460018302840111600160201b8311171561105857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612832945050505050565b61090f600480360360608110156110af57600080fd5b50803590602081013590604001356001600160a01b0316612978565b610781612990565b610739612996565b6107816129f1565b6107816129f7565b6107396004803603602081101561110157600080fd5b50356129fd565b6107816004803603602081101561111e57600080fd5b50356001600160a01b0316612a16565b6107c8612a28565b610781612a37565b610781612a3d565b6107816004803603602081101561115c57600080fd5b5035612a43565b6107816004803603602081101561117957600080fd5b5035612a9a565b610781612aaf565b610739600480360360a081101561119e57600080fd5b6001600160a01b0382351691602081013591604082013591606081013515159181019060a081016080820135600160201b8111156111db57600080fd5b8201836020820111156111ed57600080fd5b803590602001918460018302840111600160201b8311171561120e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612ab5945050505050565b610781612acc565b6107396004803603604081101561126d57600080fd5b5080359060200135612ad2565b6107396004803603602081101561129057600080fd5b5035612b18565b6107c8612b29565b6107c8612b3d565b61090f612b4c565b610781612b8f565b610739600480360360208110156112cd57600080fd5b5035612b95565b610781612bab565b610739600480360360208110156112f257600080fd5b5035612bb1565b6107396004803603606081101561130f57600080fd5b50803590602081013590604001351515612bc6565b6107c8612be5565b6107396004803603604081101561134257600080fd5b5080359060200135612bf4565b610781612c5a565b6107396004803603602081101561136d57600080fd5b5035612c60565b6107396004803603604081101561138a57600080fd5b5080359060200135612d1c565b610739600480360360408110156113ad57600080fd5b5080359060200135612d82565b610739600480360360208110156113d057600080fd5b5035612e75565b610781612e8c565b610739600480360360808110156113f557600080fd5b813591602081013591604082013515159190810190608081016060820135600160201b81111561142457600080fd5b82018360208201111561143657600080fd5b803590602001918460018302840111600160201b8311171561145757600080fd5b509092509050612e92565b610739612f43565b610781612f55565b610781612f5b565b6107396004803603604081101561149057600080fd5b506001600160a01b038135169060200135612f61565b610739600480360360408110156114bc57600080fd5b5080359060200135612f75565b610781600480360360208110156114df57600080fd5b5035612f88565b61090f600480360360608110156114fc57600080fd5b50803590602081013590604001356001600160a01b0316612fd6565b6107396004803603604081101561152e57600080fd5b50803590602001356001600160a01b0316612fed565b61090f6004803603606081101561155a57600080fd5b50803590602081013590604001356001600160a01b03166130a8565b6107396004803603602081101561158c57600080fd5b50356130b7565b610781613140565b61090f613146565b610739600480360360208110156115b957600080fd5b5035151561314f565b610781600480360360208110156115d857600080fd5b50356132a1565b610739600480360360208110156115f557600080fd5b50356132b3565b6107396004803603604081101561161257600080fd5b50803590602001356132c8565b610781613330565b6108d9613336565b6107396004803603602081101561164557600080fd5b503561333f565b6107396004803603602081101561166257600080fd5b50356001600160a01b03166133fb565b6107816004803603602081101561168857600080fd5b503561347b565b6107c861348d565b6107c861349c565b610739600480360360208110156116b557600080fd5b503515156134ab565b610739600480360360208110156116d457600080fd5b50356001600160a01b03166134c6565b610739600480360360408110156116fa57600080fd5b81359190810190604081016020820135600160201b81111561171b57600080fd5b82018360208201111561172d57600080fd5b803590602001918460018302840111600160201b8311171561174e57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506134e0945050505050565b61073960048036036101208110156117a657600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135821691608082013581169160a081013582169160c082013581169160e081013582169161010090910135166136e5565b6107396004803603602081101561180f57600080fd5b5035613888565b6107396138a3565b6107c86138b3565b6107396004803603606081101561183c57600080fd5b50803590602081013590604001356138c2565b6107816139dd565b6107c86139e3565b6107396004803603602081101561187557600080fd5b50356139f2565b611884613a07565b600f55565b611891613a07565b61189a81613a55565b6118a357600080fd5b60238054610100600160a81b0319169055602580546001600160a01b03199081166001600160a01b03938416179091556006805482169583169590951790945560058054851693821693909317909255600780549093169116179055565b60155481565b60135481565b60085481565b61191b613a07565b8061192557600080fd5b60055460105460408051630f1980a560e41b8152600481018590526024810192909252516001600160a01b039092169163f1980a509160448082019260009290919082900301818387803b15801561197c57600080fd5b505af1158015611990573d6000803e3d6000fd5b50505060109190915550565b602c546001600160a01b031681565b60065460408051632f745c5960e01b81526001600160a01b038481166004830152600060248301819052925192931691632f745c5991604480820192602092909190829003018186803b158015611a0157600080fd5b505afa158015611a15573d6000803e3d6000fd5b505050506040513d6020811015611a2b57600080fd5b505190505b919050565b80611a3f81613a74565b60026000838152601a6020526040902060060154600160a01b900460ff166003811115611a6857fe5b14611aa7576040805162461bcd60e51b815260206004820152600a602482015269139bdd081a985a5b195960b21b604482015290519081900360640190fd5b6000828152601a602052604090206003015415611aff576040805162461bcd60e51b8152602060048201526011602482015270416c726561647920756e7374616b696e6760781b604482015290519081900360640190fd5b6009546000838152601a6020526040902060040154811015611b61576040805162461bcd60e51b8152602060048201526016602482015275125b98dbdb5c1b195d19481a985a5b081c195c9a5bd960521b604482015290519081900360640190fd5b6000838152601a6020526040902054600c54811015611b7f57600080fd5b6000848152601a60205260409020600601546001600160a01b03168015611bf457806001600160a01b031663a69df4b56040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611bdb57600080fd5b505af1158015611bef573d6000803e3d6000fd5b505050505b6000858152601a60205260409020600a0154611c2490611c1b90849063ffffffff613afe16565b60016000613b10565b6000858152601a602052604080822060068101805460ff60a01b1916600160a01b1790556005908101549054825163f92ec5af60e01b8152600481018a90526001600160a01b039283166024820181905293519394929091169263f92ec5af9260448084019391929182900301818387803b158015611ca257600080fd5b505af1158015611cb6573d6000803e3d6000fd5b50505050505050505050565b60175481565b6007546001600160a01b031681565b80611ce181613a74565b611cec826001613bcc565b5050565b611cf8613a07565b600955565b611d05613a07565b6001600160a01b038116611d1857600080fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b60268181548110611d4757fe5b6000918252602090912001546001600160a01b0316905081565b600e5481565b601e602052600090815260409020805460019091015482565b6000818152601a6020526040812060068101548154600390920154600954611db593600160a01b90930460ff16929190613be0565b92915050565b611dc3613c17565b82611dcd81613a74565b611dda8484846000613c58565b50505050565b611de8612b4c565b611df157600080fd5b8051611cec906026906020840190615e39565b80611e0e81613a74565b611cec826000613e32565b6002546000906001600160a01b03163314611e3357600080fd5b600954601d546000908190611e46615e9e565b6026546040805191840180835260208082028401019091528015611e74578160200160208202803883390190505b5060408083019190915260268054825160208083028201810190945281815292830182828015611ecd57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611eaf575b50505050506060820152600060208201526026546080820152611eee615ecd565b6026546040805191850180835260208082028401019091528015611f1c578160200160208202803883390190505b50602082015260005b888110156120eb576000611f738e8c8c85818110611f3f57fe5b9050606002016003806020026040519081016040528092919082600360200280828437600092019190915250613ee5915050565b9050856001600160a01b0316816001600160a01b03161415611f9557506120e3565b856001600160a01b0316816001600160a01b03161015611fb557506120eb565b6001600160a01b0381166000908152601b6020908152604080832054808452601a909252909120805460068201546003909201548087529091600160a01b900460ff169061200790829084908e613be0565b15612092576000838152601a60205260409020600a0154939850889361204690839061203a908d9063ffffffff613afe16565b9063ffffffff613afe16565b8651909a50156120805782866020015187604001518151811061206557fe5b6020908102919091010152604086018051600101905261208d565b61208a8785613fe8565b96505b6120de565b60028160038111156120a057fe5b14156120de578287604001518860000151815181106120bb57fe5b602090810291909101810191909152875160019081018952908801805190910190525b505050505b600101611f25565b506120f7826000613fe8565b91506121198d8b878e86604001518760000151876020015188604001516140c5565b9d9c50505050505050505050505050565b8061213481613a74565b611cec826001613e32565b6006546001600160a01b031681565b60165481565b601a60205260009081526040902080546001820154600283015460038401546004850154600586015460068701546007880154600889015460098a0154600a8b0154600b909b0154999a98999798969795966001600160a01b039586169695851695600160a01b90950460ff16948d565b601b6020526000908152604090205481565b6000818152601a602052604081206003015481906121fc576121f88361422d565b9150505b6000838152601a602052604090206009015461223190600190612225908463ffffffff613afe16565b9063ffffffff6142a916565b9392505050565b612240613a07565b60038054602b80546001600160a01b038084166001600160a01b0319928316179283905592811686841617909355602c805490931684831617909255604080516370a0823160e01b81523060048201529051611cec93909216916370a0823191602480820192602092909190829003018186803b1580156122c057600080fd5b505afa1580156122d4573d6000803e3d6000fd5b505050506040513d60208110156122ea57600080fd5b50516142be565b600c5481565b60295481565b612305613a07565b6000848152601a60205260409020600601546001600160a01b03168061232a57600080fd5b6040805163abf59fc960e01b81526001600160a01b03868116600483015285811660248301526044820185905291519183169163abf59fc99160648082019260009290919082900301818387803b15801561238457600080fd5b505af1158015612398573d6000803e3d6000fd5b505050505050505050565b60006001600160a01b03821615806124315750600654604080516370a0823160e01b81526001600160a01b038581166004830152915191909216916370a08231916024808301926020929190829003018186803b15801561240357600080fd5b505afa158015612417573d6000803e3d6000fd5b505050506040513d602081101561242d57600080fd5b5051155b1561243e57506000611a30565b60065460408051632f745c5960e01b81526001600160a01b0385811660048301526000602483018190529251601a949190911691632f745c59916044808301926020929190829003018186803b15801561249757600080fd5b505afa1580156124ab573d6000803e3d6000fd5b505050506040513d60208110156124c157600080fd5b5051815260208101919091526040016000205492915050565b6000836124e68161445d565b6124f2848460016144cb565b95945050505050565b600f5481565b60105481565b61250f613c17565b61251e85858585856000614571565b5050505050565b333014612567576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b61257687888860006001614623565b6125848560095460016146f0565b60006125c888868686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061485492505050565b6005546040805163e12ab1af60e01b815260048101849052602481018a90526044810189905290519293506001600160a01b039091169163e12ab1af9160648082019260009290919082900301818387803b15801561262657600080fd5b505af115801561263a573d6000803e3d6000fd5b505050505050505050505050565b60208080526000918252604091829020805460018083015460028085015460038601805489516101009682161596909602600019011692909204601f8101889004880285018801909852878452939691956001600160a01b03851695600160a01b90950460ff16949392908301828280156127045780601f106126d957610100808354040283529160200191612704565b820191906000526020600020905b8154815290600101906020018083116126e757829003601f168201915b5050505050905085565b60195460ff1681565b60125481565b6000908152601a60205260409020600601546001600160a01b031690565b60005461010090046001600160a01b031681565b6004546001600160a01b03165b90565b6000806000fd5b61276e613a07565b60255460408051602481018690526044810185905260648082018590528251808303909101815260849091019091526020810180516001600160e01b0316633064689160e11b1790526127ca916001600160a01b031690614c61565b505050565b600654604080516331a9108f60e11b81526004810184905290516000926001600160a01b031691636352211e916024808301926020929190829003018186803b158015611a0157600080fd5b612823613c17565b611cec82338360006001614623565b6017546040805133602080830191909152818301879052825180830384018152606090920190925280519101206128719184908463ffffffff614c8916565b6128b4576040805162461bcd60e51b815260206004820152600f60248201526e2bb937b7339030b1b190383937b7b360891b604482015290519081900360640190fd5b336000908152601f60205260408120546128d590859063ffffffff6142a916565b6022549091506128eb908263ffffffff6142a916565b6022556005546040805163122b648160e01b81523360048201526024810184905290516001600160a01b039092169163122b64819160448082019260009290919082900301818387803b15801561294157600080fd5b505af1158015612955573d6000803e3d6000fd5b5050336000818152601f60205260408120889055611dda93509091508390614ddf565b6000836129848161445d565b6124f2848460006144cb565b600a5481565b61299e612b4c565b6129a757600080fd5b6001546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600180546001600160a01b0319169055565b60095481565b60185481565b612a05613a07565b612a138160095460016146f0565b50565b601f6020526000908152604090205481565b6004546001600160a01b031681565b602a5481565b600b5481565b600081612a4f8161445d565b612a5883614ec9565b6000838152601a6020526040812060090154612a7b90600163ffffffff6142a916565b6000858152601a60205260409020600160099091015592505050919050565b6000908152601a60205260409020600a015490565b601d5490565b612abd613c17565b61251e85858585856001614571565b60115481565b81612adc8161445d565b6000838152601a60205260409020600a0154612afe908363ffffffff6142a916565b6000938452601a6020526040909320600a01929092555050565b612b20613a07565b612a13816142be565b60235461010090046001600160a01b031681565b6001546001600160a01b031690565b604080517f6d617469632e6e6574776f726b2e70726f78792e6f776e6572000000000000008152905190819003601901902054336001600160a01b039091161490565b60095490565b612b9d613a07565b612a138160095460006146f0565b60275481565b80612bbb81613a74565b611cec826000613bcc565b612bce613c17565b82612bd881613a74565b611dda8484846001613c58565b6002546001600160a01b031681565b612bfc613c17565b602554604080516024810185905260448101849052306064808301919091528251808303909101815260849091019091526020810180516001600160e01b031663561ad5c960e11b179052611cec916001600160a01b031690614c61565b60225481565b612c68613a07565b6005546016546040805163a3b1d8cb60e01b8152600481018590526024810192909252516001600160a01b039092169163a3b1d8cb9160448082019260009290919082900301818387803b158015612cbf57600080fd5b505af1158015612cd3573d6000803e3d6000fd5b505050506064811115612d17576040805162461bcd60e51b8152602060048201526007602482015266746f6f2062696760c81b604482015290519081900360640190fd5b601655565b612d24612b4c565b612d2d57600080fd5b602554604080516024810185905260448082018590528251808303909101815260649091019091526020810180516001600160e01b0316639ddbbf8560e01b179052611cec916001600160a01b031690614c61565b81612d8c8161445d565b6000821315612de55760195460ff16612de5576040805162461bcd60e51b815260206004820152601660248201527511195b1959d85d1a5bdb881a5cc8191a5cd8589b195960521b604482015290519081900360640190fd5b6000838152601a602052604090206003015480612e0d57612e0883600080613b10565b612e50565b600954811115612e50576040805162461bcd60e51b8152602060048201526009602482015268756e7374616b696e6760b81b604482015290519081900360640190fd5b60008312612e6757612e628484614ed8565b611dda565b611dda848460001902612ad2565b612e7d613a07565b80612e8757600080fd5b600e55565b601c5490565b612e9a613c17565b6025546040516024810187815260448201879052851515606483015260806084830190815260a4830185905261251e936001600160a01b03169263a685487760e01b928a928a928a928a928a9260c40184848082843760008184015260408051601f19601f9093018316909401848103909201845252506020810180516001600160e01b03199a909a166001600160e01b03909a169990991790985250614c6195505050505050565b612f4b613a07565b612f53614f13565b565b60085490565b60245481565b612f69613a07565b611cec82826001614ddf565b612f7d613a07565b600c91909155600d55565b6000818152601a60205260408120600301548190612fad57612fa98361422d565b5090505b6000838152601a602052604090206001908101546122319190612225908463ffffffff613afe16565b6000612fe58484846000614f1f565b949350505050565b612ff5613a07565b306001600160a01b0316816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561303857600080fd5b505afa15801561304c573d6000803e3d6000fd5b505050506040513d602081101561306257600080fd5b50516001600160a01b03161461307757600080fd5b6000918252601a602052604090912060060180546001600160a01b0319166001600160a01b03909216919091179055565b6000612fe58484846001614f1f565b6130bf613a07565b806130c957600080fd5b600554600b5460408051632dbe9d3160e21b8152600481018590526024810192909252516001600160a01b039092169163b6fa74c49160448082019260009290919082900301818387803b15801561312057600080fd5b505af1158015613134573d6000803e3d6000fd5b505050600b9190915550565b60145481565b60005460ff1681565b336000908152601b6020908152604080832054808452601a9092529091206006810154815460039092015460095461319493600160a01b90930460ff16929190613be0565b6131d5576040805162461bcd60e51b815260206004820152600d60248201526c3737ba103b30b634b230ba37b960991b604482015290519081900360640190fd5b6000818152601a60205260409020600601546001600160a01b03168061323b576040805162461bcd60e51b815260206004820152601660248201527511195b1959d85d1a5bdb881a5cc8191a5cd8589b195960521b604482015290519081900360640190fd5b604080516303dd464160e51b8152841515600482015290516001600160a01b03831691637ba8c82091602480830192600092919082900301818387803b15801561328457600080fd5b505af1158015613298573d6000803e3d6000fd5b50505050505050565b60216020526000908152604090205481565b806132bd81613a74565b611cec8260006150ae565b816132d281613a74565b6132db83614ec9565b602554604080516024810186905260448082018690528251808303909101815260649091019091526020810180516001600160e01b0316636e6cb15960e11b1790526127ca916001600160a01b031690614c61565b60285481565b601c54601d5482565b613347613a07565b6000811161335457600080fd5b600554600a5460408051635071805360e11b8152600481018590526024810192909252516001600160a01b039092169163a0e300a69160448082019260009290919082900301818387803b1580156133ab57600080fd5b505af11580156133bf573d6000803e3d6000fd5b505050600a8290555060088190556133de81600463ffffffff61528c16565b60158190556009546133f59163ffffffff613afe16565b60185550565b613403612b4c565b61340c57600080fd5b6001600160a01b03811661341f57600080fd5b6002546040516001600160a01b038084169216907f211c9015fc81c0dbd45bd99f0f29fc1c143bfd53442d5ffd722bbbef7a887fe990600090a3600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000908152601a602052604090205490565b602b546001600160a01b031681565b6005546001600160a01b031681565b6134b3613a07565b6019805460ff1916911515919091179055565b6134ce612b4c565b6134d757600080fd5b612a13816152ae565b816134ea81613a74565b60006134f58361531d565b600954600f54600087815260216020526040902054929350909161351e9163ffffffff613afe16565b811015613560576040805162461bcd60e51b815260206004820152600b60248201526a139bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b6000858152601a602090815260408083206005908101549054915163b80fbce560e01b8152600481018a81526001600160a01b039283166024830181905288841660448401526080606484019081528b5160848501528b519197949095169563b80fbce5958d9589958c958f95909460a490920192918601918190849084905b838110156135f85781810151838201526020016135e0565b50505050905090810190601f1680156136255780820380516001836020036101000a031916815260200191505b5095505050505050600060405180830381600087803b15801561364757600080fd5b505af115801561365b573d6000803e3d6000fd5b5050506000878152601a60205260409020600301541515905061368a57613681816153d6565b61368a836154e0565b6001600160a01b039081166000908152601b60209081526040808320600019905594909216808252848220889055968152601a825283812060050180546001600160a01b031916909717909655602190529320929092555050565b60235460ff161561372e576040805162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481a5b9a5d195960921b604482015290519081900360640190fd5b6023805460ff1916600117905561374481613a55565b61378e576040805162461bcd60e51b8152602060048201526016602482015275185d58dd1a5bdb881a5b5c1b081a5b98dbdc9c9958dd60521b604482015290519081900360640190fd5b602580546001600160a01b03199081166001600160a01b038481169190911790925560008054610100600160a81b031916610100878516021790556004805482168c84161790556002805482168b84161790556003805482168a84161790556006805482168984161790556005805482168884161790556007805490911691861691909117905561381e826152ae565b5050612000600855505060016009819055610376600a90815569044664c7bf6451f00000600b55670de0b6b3a7640000600c819055600d55610400600e556064600f55600760105560128290556108006015556016556019805460ff191690911790555050505050565b613890613a07565b6009546133f5908263ffffffff613afe16565b6138ab613a07565b612f536155fa565b6025546001600160a01b031681565b6007821161390b576040805162461bcd60e51b815260206004820152601160248201527024b73b30b634b21036b4b3b930ba34b7b760791b604482015290519081900360640190fd5b6000838152601a6020526040808220600601548151636e7ce59160e01b81523360048201526024810185905291516001600160a01b0390911692636e7ce591926044808201939182900301818387803b15801561396757600080fd5b505af115801561397b573d6000803e3d6000fd5b5050506000838152601a6020526040808220600601548151632830728d60e21b81523360048201526024810186905291516001600160a01b03909116935063a0c1ca349260448084019391929182900301818387803b15801561328457600080fd5b600d5481565b6003546001600160a01b031681565b806139fc81613a74565b611cec8260016150ae565b60005461010090046001600160a01b03163314612f535760405162461bcd60e51b8152600401808060200182810382526026815260200180615f6b6026913960400191505060405180910390fd5b60006001600160a01b038216613a6d57506000611a30565b503b151590565b600654604080516331a9108f60e11b815260048101849052905133926001600160a01b031691636352211e916024808301926020929190829003018186803b158015613abf57600080fd5b505afa158015613ad3573d6000803e3d6000fd5b505050506040513d6020811015613ae957600080fd5b50516001600160a01b031614612a1357600080fd5b60008282018381101561223157600080fd5b80613baa576000831315613b3957601c54613b31908463ffffffff613afe16565b601c55613b5d565b6000831215613b5d57601c54613b5990600085900363ffffffff6142a916565b601c555b6000821315613b8157601d54613b79908363ffffffff613afe16565b601d55613ba5565b6000821215613ba557601d54613ba190600084900363ffffffff6142a916565b601d555b6127ca565b6000818152601e60205260409020805484018155600101805483019055505050565b613bd582614ec9565b611cec823383615609565b60008084118015613bf85750821580613bf857508183115b80156124f257506001856003811115613c0d57fe5b1495945050505050565b60005460ff1615612f53576040805162461bcd60e51b81526020600482015260066024820152651b1bd8dad95960d21b604482015290519081900360640190fd5b6000848152601a602052604090206003015415613cab576040805162461bcd60e51b815260206004820152600c60248201526b4e6f2072657374616b696e6760a01b604482015290519081900360640190fd5b8215613cbd57613cbd333085846156e0565b613cc684614ec9565b8115613d0d576000848152601a60205260409020600190810154613cf6919061222590869063ffffffff613afe16565b6000858152601a6020526040902060019081015592505b601154600090613d23908563ffffffff613afe16565b60118190556000868152601a6020526040902054909150613d4a908563ffffffff613afe16565b6000868152601a6020526040812091909155613d6890859080613b10565b6005546040805163532e19a960e01b81526004810188905290516001600160a01b039092169163532e19a99160248082019260009290919082900301818387803b158015613db557600080fd5b505af1158015613dc9573d6000803e3d6000fd5b50506005546000888152601a6020526040808220548151631585a9f360e21b8152600481018c905260248101919091526044810187905290516001600160a01b039093169450635616a7cc93506064808201939182900301818387803b15801561238457600080fd5b600082815260208052604090205415613e4a57600080fd5b6000828152601a602052604090206006810154600290910154600160a01b90910460ff169015801590613e8c57506000838152601a6020526040902060030154155b8015613eb857506001816003811115613ea157fe5b1480613eb857506002816003811115613eb657fe5b145b613ec157600080fd5b600954600090613ed890600163ffffffff613afe16565b9050611dda8482856146f0565b805160208201516040830151600092919060ff167f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115613f2d5760009350505050611db5565b601b8160ff161015613f3d57601b015b8060ff16601b14158015613f5557508060ff16601c14155b15613f665760009350505050611db5565b60408051600080825260208083018085528a905260ff85168385015260608301879052608083018690529251909260019260a080820193601f1981019281900390910190855afa158015613fbe573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116613fde57600080fd5b9695505050505050565b613ff0615e9e565b826080015183602001511080156140345750816001600160a01b0316836060015184602001518151811061402057fe5b60200260200101516001600160a01b031614155b156140b557601b6000846060015185602001518151811061405157fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054836040015184600001518151811061408e57fe5b60209081029190910181019190915283516001908101855290840180519091019052613ff0565b5050602081018051600101905290565b601c546000906140f2600161203a60036140e685600263ffffffff6157e116565b9063ffffffff61528c16565b88101561413c576040805162461bcd60e51b8152602060048201526013602482015272322f332b31206e6f6e2d6d616a6f726974792160681b604482015290519081900360640190fd5b60006141498b8a84615808565b9050600061416760646140e6601654856157e190919063ffffffff16565b6001600160a01b038c166000908152601b6020908152604080832054808452601a909252909120600181015492935090916141a8908463ffffffff613afe16565b600182015560178b905560006141f56141e68e6140e66a084595161401484a0000006141da8a8a63ffffffff6142a916565b9063ffffffff6157e116565b6024549063ffffffff613afe16565b90506142028b8b8361595c565b602481905561421289898361595c565b61421a615990565b50929d9c50505050505050505050505050565b6000818152601a602052604081208054600a90910154829190829061425990839063ffffffff613afe16565b6000868152601a60205260409020600b0154602454919250900361429d86846142976a084595161401484a0000006140e6868863ffffffff6157e116565b85615a05565b94509450505050915091565b6000828211156142b857600080fd5b50900390565b602b54604080516370a0823160e01b8152306004820152905183926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561430857600080fd5b505afa15801561431c573d6000803e3d6000fd5b505050506040513d602081101561433257600080fd5b50511015614377576040805162461bcd60e51b815260206004820152600d60248201526c4c61636b696e67204d4154494360981b604482015290519081900360640190fd5b602b54602c546040805163095ea7b360e01b81526001600160a01b039283166004820152602481018590529051919092169163095ea7b39160448083019260209291908290030181600087803b1580156143d057600080fd5b505af11580156143e4573d6000803e3d6000fd5b505050506040513d60208110156143fa57600080fd5b5050602c54604080516308a960c160e31b81526004810184905290516001600160a01b039092169163454b06089160248082019260009290919082900301818387803b15801561444957600080fd5b505af115801561251e573d6000803e3d6000fd5b6000818152601a60205260409020600601546001600160a01b03163314612a13576040805162461bcd60e51b815260206004820152601860248201527f496e76616c696420636f6e747261637420616464726573730000000000000000604482015290519081900360640190fd5b6000806144d783615a99565b604080516323b872dd60e01b81526001600160a01b038781166004830152306024830152604482018990529151929350600092918416916323b872dd9160648082019260209290919082900301818787803b15801561453557600080fd5b505af1158015614549573d6000803e3d6000fd5b505050506040513d602081101561455f57600080fd5b50519050836124f2576124f2866142be565b60105461457c612aaf565b106145be576040805162461bcd60e51b815260206004820152600d60248201526c6e6f206d6f726520736c6f747360981b604482015290519081900360640190fd5b600c5485101561460a576040805162461bcd60e51b81526020600482015260126024820152711b9bdd08195b9bdd59da0819195c1bdcda5d60721b604482015290519081900360640190fd5b6146178633868885614623565b61329886868585614854565b600d5483101561466a576040805162461bcd60e51b815260206004820152600d60248201526c199959481d1bdbc81cdb585b1b609a1b604482015290519081900360640190fd5b614685843061467f868663ffffffff613afe16565b846156e0565b602254614698908463ffffffff613afe16565b6022556005546040805163a449d79560e01b81526001600160a01b038881166004830152602482018790529151919092169163a449d79591604480830192600092919082900301818387803b15801561238457600080fd5b6146f983614ec9565b6000838152601a602052604081205490614712856127cf565b6000868152601a6020526040902060038101869055600a810154600690910154919250906001600160a01b0316801561479957806001600160a01b031663f83d08ba6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561478057600080fd5b505af1158015614794573d6000803e3d6000fd5b505050505b6000878152601a60205260409020600501546147bd906001600160a01b03166153d6565b6147c8878487615609565b60006009548711156147da57866147dd565b60005b90506147f183860160000360001983613b10565b60055460408051635e04d48360e01b81526001600160a01b038781166004830152602482018c9052604482018b90526064820189905291519190921691635e04d48391608480830192600092919082900301818387803b15801561262657600080fd5b6000806148608361531d565b600954601254600554601154939450919290916001600160a01b031690600090614890908a63ffffffff613afe16565b905080601181905550604051806101a001604052808a8152602001600181526020018581526020016000815260200160008152602001866001600160a01b03168152602001896148e157600061496d565b600754600480546040805163d4ad267360e01b81529283018990526001600160a01b03888116602485015291821660448401525192169163d4ad2673916064808201926020929091908290030181600087803b15801561494057600080fd5b505af1158015614954573d6000803e3d6000fd5b505050506040513d602081101561496a57600080fd5b50515b6001600160a01b031681526020016001815260006020808301829052604080840183905260016060808601829052608080870186905260245460a0978801528a8652601a855294839020875181559387015191840191909155908501516002830155840151600380830191909155918401516004820155918301516005830180546001600160a01b039283166001600160a01b03199182161790915560c08501516006850180549190931691161780825560e08501519260ff60a01b1990911690600160a01b908490811115614a3f57fe5b0217905550610100820151600782015561012082015160088201556101408201516009820155610160820151600a82015561018090910151600b9091015560008381526021602052604080822086905560065481516340c10f1960e01b81526001600160a01b038e8116600483015260248201889052925192909116926340c10f199260448084019382900301818387803b158015614add57600080fd5b505af1158015614af1573d6000803e3d6000fd5b5050506001600160a01b0386166000908152601b60205260408120859055614b1e91508a90600190613b10565b836020600085815260200190815260200160002060010181905550816001600160a01b03166333a8383c868986888e876040518763ffffffff1660e01b815260040180876001600160a01b03166001600160a01b0316815260200180602001868152602001858152602001848152602001838152602001828103825287818151815260200191508051906020019080838360005b83811015614bca578181015183820152602001614bb2565b50505050905090810190601f168015614bf75780820380516001836020036101000a031916815260200191505b50975050505050505050600060405180830381600087803b158015614c1b57600080fd5b505af1158015614c2f573d6000803e3d6000fd5b50505050614c47600184613afe90919063ffffffff16565b601255614c53856154e0565b509098975050505050505050565b600080825160208401856127105a03f43d604051816000823e828015614c85578282f35b8282fd5b60006020825181614c9657fe5b0615614ce0576040805162461bcd60e51b8152602060048201526014602482015273092dcecc2d8d2c840e0e4dedecc40d8cadccee8d60631b604482015290519081900360640190fd5b60006020835181614ced57fe5b0490508060020a8510614d3f576040805162461bcd60e51b81526020600482015260156024820152744c65616620696e64657820697320746f6f2062696760581b604482015290519081900360640190fd5b60008660205b85518111614dd15785810151925060028806614d915781836040516020018083815260200182815260200192505050604051602081830303815290604052805190602001209150614dc3565b828260405160200180838152602001828152602001925050506040516020818303038152906040528051906020012091505b600288049750602001614d45565b509094149695505050505050565b80614ded57614ded82615ac2565b6000614df882615a99565b9050806001600160a01b031663a9059cbb85856040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015614e5a57600080fd5b505af1158015614e6e573d6000803e3d6000fd5b505050506040513d6020811015614e8457600080fd5b5051611dda576040805162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b604482015290519081900360640190fd5b612a1381602454602454615c4b565b6000828152601a60205260409020600a0154614efa908263ffffffff613afe16565b6000928352601a6020526040909220600a019190915550565b6000805460ff19169055565b6000848152601a60205260408120600601546001600160a01b0316331480614fbe57506004805460408051631ab0168360e31b8152905133936001600160a01b039093169263d580b41892808201926020929091829003018186803b158015614f8757600080fd5b505afa158015614f9b573d6000803e3d6000fd5b505050506040513d6020811015614fb157600080fd5b50516001600160a01b0316145b614ffd576040805162461bcd60e51b815260206004820152600b60248201526a1b9bdd08185b1b1bddd95960aa1b604482015290519081900360640190fd5b8161500b5761500b84615ac2565b600061501683615a99565b9050806001600160a01b031663a9059cbb85876040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561507857600080fd5b505af115801561508c573d6000803e3d6000fd5b505050506040513d60208110156150a257600080fd5b50519695505050505050565b6000828152601a602052604090206003015480158015906150e457506009546008546150e190839063ffffffff613afe16565b11155b8015615117575060036000848152601a6020526040902060060154600160a01b900460ff16600381111561511457fe5b14155b61512057600080fd5b6000838152601a6020526040812054601154909190615145908363ffffffff6142a916565b60118190559050615157853386615609565b60065460408051630852cd8d60e31b81526004810188905290516001600160a01b03909216916342966c689160248082019260009290919082900301818387803b1580156151a457600080fd5b505af11580156151b8573d6000803e3d6000fd5b5050506000868152601a6020526040812081815560048101919091556005810180546001600160a01b03191690556000197f584f46c60af19681376031579adb04a2416e54ee5505351c2a8435e3766026ea55600601805460ff60a01b1916600360a01b1790555061522b338386614ddf565b6005546040805163ae2e26b160e01b815233600482015260248101889052604481018590526064810184905290516001600160a01b039092169163ae2e26b19160848082019260009290919082900301818387803b15801561238457600080fd5b600080821161529a57600080fd5b60008284816152a557fe5b04949350505050565b6001600160a01b0381166152c157600080fd5b6001546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000815160401461535f576040805162461bcd60e51b81526020600482015260076024820152663737ba10383ab160c91b604482015290519081900360640190fd5b815160208301206001600160a01b0381161580159061539457506001600160a01b0381166000908152601b6020526040902054155b611db5576040805162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b604482015290519081900360640190fd5b602680549060009060001983018381106153ec57fe5b600091825260209091200154602680546001600160a01b03909216925090600019840190811061541857fe5b600091825260209091200180546001600160a01b031916905560001982015b80156154cf57836001600160a01b0316826001600160a01b0316141561545c576154cf565b6026600182038154811061546c57fe5b9060005260206000200160009054906101000a90046001600160a01b0316826026600184038154811061549b57fe5b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055915060001901615437565b506000198201611dda602682615eee565b6026805460018101825560008290527f744a2cf8fd7008e3d53b67916e73460df9fa5214e3ef23dd4259ca09493a35940180546001600160a01b0319166001600160a01b0384161790555460001901805b80156155b25760006026600183038154811061554957fe5b6000918252602090912001546001600160a01b039081169150841681101561557157506155b2565b806026838154811061557f57fe5b600091825260209091200180546001600160a01b0319166001600160a01b03929092169190911790555060001901615531565b8181146127ca5782602682815481106155c757fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505050565b6000805460ff19166001179055565b6000838152601a6020526040812060019081015461562c9163ffffffff6142a916565b601454909150615642908263ffffffff613afe16565b6014556000848152601a60205260409020600190810155615664838284614ddf565b60055460145460408051635b42d93560e11b815260048101889052602481018590526044810192909252516001600160a01b039092169163b685b26a9160648082019260009290919082900301818387803b1580156156c257600080fd5b505af11580156156d6573d6000803e3d6000fd5b5050505050505050565b60006156eb82615a99565b604080516323b872dd60e01b81526001600160a01b0388811660048301528781166024830152604482018790529151929350908316916323b872dd916064808201926020929091908290030181600087803b15801561574957600080fd5b505af115801561575d573d6000803e3d6000fd5b505050506040513d602081101561577357600080fd5b50516157bd576040805162461bcd60e51b81526020600482015260146024820152731d1c985b9cd9995c88199c9bdb4819985a5b195960621b604482015290519081900360640190fd5b811580156157d357506001600160a01b03841630145b1561251e5761251e836142be565b6000826157f057506000611db5565b828202828482816157fd57fe5b041461223157600080fd5b600e54600b54600091908261582883888161581f57fe5b04602954615d1b565b905060008111801561583c57506027548114155b1561587d57602754156158775760006064602a5484028161585957fe5b04905081602754111561586f5791820191615875565b80830392505b505b60278190555b600083881115615916576028546158c56158b560646140e66158a860026000198901890204866157e1565b889063ffffffff6157e116565b612225868663ffffffff6157e116565b91506158e76158da848763ffffffff6157e116565b8a9063ffffffff6142a916565b985061591261590560646140e6846141da898963ffffffff6157e116565b859063ffffffff6142a916565b9350505b61593a61592d856140e68b8763ffffffff6157e116565b829063ffffffff613afe16565b9050615950866140e6838a63ffffffff6157e116565b98975050505050505050565b60245460005b8381101561251e5761598885828151811061597957fe5b60200260200101518385615c4b565b600101615962565b60095460006159a682600163ffffffff613afe16565b90506159b0615f12565b506000818152601e602090815260408083208151808301909252805480835260019091015492820183905290926159e79290613b10565b506000918252601e6020526040822082815560010191909155600955565b60008082615a1857506000905080615a90565b6000615a2e846140e6888863ffffffff6157e116565b6000888152601a60205260409020600701549091508015615a7557615a72615a6560646140e6846141da8b8863ffffffff6142a916565b839063ffffffff613afe16565b91505b6000615a87878463ffffffff6142a916565b92945091925050505b94509492505050565b600081615ab157602b546001600160a01b0316611db5565b50506003546001600160a01b031690565b600354604080516370a0823160e01b8152306004820152905183926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015615b0c57600080fd5b505afa158015615b20573d6000803e3d6000fd5b505050506040513d6020811015615b3657600080fd5b50511015615b79576040805162461bcd60e51b815260206004820152600b60248201526a131858dada5b99c81413d360aa1b604482015290519081900360640190fd5b600354602c546040805163095ea7b360e01b81526001600160a01b039283166004820152602481018590529051919092169163095ea7b39160448083019260209291908290030181600087803b158015615bd257600080fd5b505af1158015615be6573d6000803e3d6000fd5b505050506040513d6020811015615bfc57600080fd5b5050602c546040805163efeff0c160e01b81526004810184905290516001600160a01b039092169163efeff0c19160248082019260009290919082900301818387803b15801561444957600080fd5b6000838152601a60205260409020600301548015801590615c6e57508060095410155b15615c7957506127ca565b6000848152601a60205260409020600b015483811015615cf8576000858152601a602052604090208054600a909101548015615ce0576000615cc1838363ffffffff613afe16565b9050615cda888484615cd58c868d8b615d31565b615d55565b50615cf5565b615cf587615cf089858a88615d31565b615dfb565b50505b8083111561251e576000858152601a60205260409020600b018390555050505050565b6000818310615d2a5781612231565b5090919050565b6000818303613fde6a084595161401484a0000006140e6838863ffffffff6157e116565b6000615d67838563ffffffff613afe16565b9050600080615d7887878686615a05565b90925090508015615db8576000878152601a6020526040902060090154615da5908263ffffffff613afe16565b6000888152601a60205260409020600901555b8115613298576000878152601a6020526040902060010154615de0908363ffffffff613afe16565b6000888152601a602052604090206001015550505050505050565b8015611cec576000828152601a6020526040902060010154615e23908263ffffffff613afe16565b6000838152601a60205260409020600101555050565b828054828255906000526020600020908101928215615e8e579160200282015b82811115615e8e57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190615e59565b50615e9a929150615f2c565b5090565b6040518060a0016040528060008152602001600081526020016060815260200160608152602001600081525090565b60405180606001604052806000815260200160608152602001600081525090565b8154818355818111156127ca576000838152602090206127ca918101908301615f50565b604051806040016040528060008152602001600081525090565b61275c91905b80821115615e9a5780546001600160a01b0319168155600101615f32565b61275c91905b80821115615e9a5760008155600101615f5656fe4f6e6c7920676f7665726e616e636520636f6e747261637420697320617574686f72697a6564a265627a7a723158202144f16fe19a38e4b93eaa1e2c04f33e2a9f779412c9defdf18d621af20c242664736f6c63430005110032", + "nonce": "0x8c", + "chainId": "0xaa36a7" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0xae07c932b4a5459bd683767dde161e9fa7ad1cc9b0ac83a39f9c291bcb22b79f", + "transactionType": "CREATE", + "contractName": null, + "contractAddress": "0x19b0b3256b22116096a2ef8cafc6e832ba18a947", + "function": null, + "arguments": null, + "transaction": { + "from": "0x0724d72eb61e508d81ca701881f2248f092953bf", + "gas": "0x3b3afb", + "value": "0x0", + "input": "0x60806040526003805460ff60a81b191690553480156200001e57600080fd5b5060038054610100338102610100600160a81b0319909216919091179182905560405191046001600160a01b0316906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3620000886001600160e01b036200008e16565b620000a3565b6003805460ff60a81b1916600160a81b179055565b61349680620000b36000396000f3fe608060405234801561001057600080fd5b50600436106103c55760003560e01c80638759c234116101ff578063b6658d071161011a578063e0db556b116100ad578063e97fddc21161007c578063e97fddc2146109aa578063eaf43bb5146109c7578063f2fde38b14610a05578063f83d08ba14610a2b576103c5565b8063e0db556b14610936578063e4457a8a1461093e578063e4cd1aec14610961578063e570b78b14610987576103c5565b8063c83ec04d116100e9578063c83ec04d146108d5578063cf309012146108f8578063dd62ed3e14610900578063df5cf7231461092e576103c5565b8063b6658d071461089a578063b89b63c1146108a2578063bfb18f29146108c5578063c7b8981c146108cd576103c5565b80639b2cb5d811610192578063a9059cbb11610161578063a9059cbb146107d8578063abf59fc914610804578063b4988fd01461083a578063b60c76fa1461086e576103c5565b80639b2cb5d814610770578063a0c1ca3414610778578063a457c2d7146107a4578063a69df4b5146107d0576103c5565b80638d16a14a116101ce5780638d16a14a146107505780638da5cb5b146107585780638f32d59b146107605780639ad5f5a414610768576103c5565b80638759c2341461071b578063883b455f146107385780638ccdd289146107405780638d086da414610748576103c5565b80634f91440d116102ef5780636ab1507111610282578063715018a611610251578063715018a6146106c05780637542ff95146106c8578063795be587146106d05780637ba8c820146106fc576103c5565b80636ab15071146106225780636cbb6050146106455780636e7ce5911461066e57806370a082311461069a576103c5565b80635f0c80cc116102be5780635f0c80cc146105a35780636035083f146105ab578063653ec134146105d6578063676e5550146105fc576103c5565b80634f91440d1461056c5780635adc6dde146105745780635c42c733146105935780635c5f7dae1461059b576103c5565b806323b872dd116103675780633a09bf44116103365780633a09bf44146105305780633ba0b9a9146105385780633d94eb0514610540578063446a2ec814610564576103c5565b806323b872dd146104a05780633046c204146104d657806339509351146104fc57806339c31e9314610528576103c5565b80631bf494a7116103a35780631bf494a7146104495780631e7ff8f614610451578063232e5415146104905780632344067914610498576103c5565b8063029d3040146103ca578063095ea7b3146103ef57806318160ddd1461042f575b600080fd5b6103ed600480360360408110156103e057600080fd5b5080359060200135610a33565b005b61041b6004803603604081101561040557600080fd5b506001600160a01b038135169060200135610a43565b604080519115158252519081900360200190f35b610437610a5a565b60408051918252519081900360200190f35b610437610a61565b6104776004803603602081101561046757600080fd5b50356001600160a01b0316610aed565b6040805192835260208301919091528051918290030190f35b6103ed610b4d565b610437610b59565b61041b600480360360608110156104b657600080fd5b506001600160a01b03813581169160208101359091169060400135610b5f565b610437600480360360208110156104ec57600080fd5b50356001600160a01b0316610bb7565b61041b6004803603604081101561051257600080fd5b506001600160a01b038135169060200135610bc9565b610437610c05565b610437610c0b565b610437610c11565b610548610cce565b604080516001600160a01b039092168252519081900360200190f35b610437610cdd565b610477610ce3565b6104776004803603602081101561058a57600080fd5b50351515610cf8565b610437610ff1565b610437610ff7565b610437610ffd565b6103ed600480360360608110156105c157600080fd5b50803590602081013590604001351515611003565b610477600480360360208110156105ec57600080fd5b50356001600160a01b03166111fe565b6104376004803603602081101561061257600080fd5b50356001600160a01b0316611217565b6104376004803603604081101561063857600080fd5b508035906020013561122a565b6104376004803603606081101561065b57600080fd5b5080359060208101359060400135611238565b6103ed6004803603604081101561068457600080fd5b506001600160a01b03813516906020013561136f565b610437600480360360208110156106b057600080fd5b50356001600160a01b03166115fb565b6103ed611616565b610548611677565b610477600480360360408110156106e657600080fd5b506001600160a01b038135169060200135611686565b6103ed6004803603602081101561071257600080fd5b503515156116aa565b6103ed6004803603602081101561073157600080fd5b50356116ce565b6105486116dc565b6104376116eb565b6104376116f1565b6103ed6116f7565b610548611701565b61041b611715565b61047761172b565b610437611738565b6103ed6004803603604081101561078e57600080fd5b506001600160a01b03813516906020013561173e565b61041b600480360360408110156107ba57600080fd5b506001600160a01b03813516906020013561176c565b6103ed6117a8565b61041b600480360360408110156107ee57600080fd5b506001600160a01b0381351690602001356117c1565b6103ed6004803603606081101561081a57600080fd5b506001600160a01b038135811691602081013590911690604001356117cf565b6103ed6004803603606081101561085057600080fd5b508035906001600160a01b03602082013581169160400135166118f6565b61041b6004803603604081101561088457600080fd5b506001600160a01b0381351690602001356119be565b6105486119cc565b6103ed600480360360408110156108b857600080fd5b50803590602001356119db565b6104376119e7565b6103ed611a2e565b6103ed600480360360408110156108eb57600080fd5b5080359060200135611a38565b61041b611a44565b6104376004803603604081101561091657600080fd5b506001600160a01b0381358116916020013516611a4d565b61041b611a78565b6103ed611a81565b6104376004803603604081101561095457600080fd5b5080359060200135611a8b565b6104376004803603602081101561097757600080fd5b50356001600160a01b0316611a99565b6103ed6004803603604081101561099d57600080fd5b5080359060200135611aab565b6103ed600480360360208110156109c057600080fd5b5035611ab7565b610437600480360360c08110156109dd57600080fd5b5080359060208101359060408101359060ff6060820135169060808101359060a00135611ac2565b6103ed60048036036020811015610a1b57600080fd5b50356001600160a01b0316611cab565b6103ed611cc5565b610a3f82826000611cde565b5050565b6000610a50338484611e8e565b5060015b92915050565b6002545b90565b6005546006546040805163072c21ef60e31b8152600481019290925251600092610ae8926001600160a01b03909116916339610f7891602480820192602092909190829003018186803b158015610ab757600080fd5b505afa158015610acb573d6000803e3d6000fd5b505050506040513d6020811015610ae157600080fd5b5051611ec6565b905090565b6000806000610afb846115fb565b90506000610b07610c11565b905081610b1b57600093509150610b489050565b610b42610b26611f1d565b610b36838563ffffffff611f4416565b9063ffffffff611f6b16565b93509150505b915091565b610b576001611f8d565b565b60095481565b6000610b6c84848461205a565b6001600160a01b038416600090815260016020908152604080832033808552925290912054610bac918691610ba7908663ffffffff61212516565b611e8e565b5060015b9392505050565b60146020526000908152604090205481565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091610a50918590610ba7908663ffffffff61213a16565b60075481565b600d5481565b600080610c1c610a5a565b90506000610c28611f1d565b90508115610cc55760055460065460408051637f4b432360e01b8152600481019290925251610cc0928592610b369286926001600160a01b031691637f4b4323916024808301926020929190829003018186803b158015610c8857600080fd5b505afa158015610c9c573d6000803e3d6000fd5b505050506040513d6020811015610cb257600080fd5b50519063ffffffff611f4416565b610cc7565b805b9250505090565b6004546001600160a01b031681565b600c5481565b600080610cf06000610cf8565b915091509091565b6000803381610d068261214c565b90506000600a54821015610d61576040805162461bcd60e51b815260206004820152601c60248201527f546f6f20736d616c6c207265776172647320746f2072657374616b6500000000604482015290519081900360640190fd5b8115610b4257610d73826000856121fa565b905080821115610f615785610e14576005546006546040805163bc8756a960e01b8152600481019290925283850360248301526001600160a01b038681166044840152905192169163bc8756a9916064808201926020929091908290030181600087803b158015610de357600080fd5b505af1158015610df7573d6000803e3d6000fd5b505050506040513d6020811015610e0d57600080fd5b5051610ea2565b6005546006546040805163c7f067cb60e01b8152600481019290925283850360248301526001600160a01b038681166044840152905192169163c7f067cb916064808201926020929091908290030181600087803b158015610e7557600080fd5b505af1158015610e89573d6000803e3d6000fd5b505050506040513d6020811015610e9f57600080fd5b50515b610ee9576040805162461bcd60e51b8152602060048201526013602482015272496e737566666963656e74207265776172647360681b604482015290519081900360640190fd5b600480546006546040805163b7721d2d60e01b8152938401919091526001600160a01b0386811660248501528486036044850152905191169163b7721d2d91606480830192600092919082900301818387803b158015610f4857600080fd5b505af1158015610f5c573d6000803e3d6000fd5b505050505b6000610f6c84610aed565b506004805460065460408051637f88a95760e01b8152938401919091526001600160a01b0388811660248501526044840185905290519394501691637f88a9579160648082019260009290919082900301818387803b158015610fce57600080fd5b505af1158015610fe2573d6000803e3d6000fd5b50505050509350915050915091565b600f5481565b60065481565b600b5481565b6000806110118585856124b9565b336000908152601460205260408120549294509092509061103990600163ffffffff61213a16565b9050611043613447565b6040518060400160405280848152602001600560009054906101000a90046001600160a01b03166001600160a01b031663900cf0cf6040518163ffffffff1660e01b815260040160206040518083038186803b1580156110a257600080fd5b505afa1580156110b6573d6000803e3d6000fd5b505050506040513d60208110156110cc57600080fd5b50519052336000818152601560209081526040808320878452825280832085518155858301516001909101559282526014905220839055905061110d612685565b60065460408051632a9b5b4160e11b81526004810192909252336024830152604482018a90526064820187905260848201859052516001600160a01b039290921691635536b6829160a48082019260009290919082900301818387803b15801561117657600080fd5b505af115801561118a573d6000803e3d6000fd5b5050600480546006546040805163532e19a960e01b815293840191909152516001600160a01b03909116935063532e19a99250602480830192600092919082900301818387803b1580156111dd57600080fd5b505af11580156111f1573d6000803e3d6000fd5b5050505050505050505050565b6012602052600090815260409020805460019091015482565b6000610a5482611225610a61565b6127c2565b6000610bb083836000612843565b6000611242611715565b61124b57600080fd5b600f546000611260858363ffffffff61213a16565b90508061127257600092505050610bb0565b6000611297611287888463ffffffff61213a16565b610b36848863ffffffff611f4416565b905060006112af83610b36868563ffffffff611f4416565b905060006112c3838363ffffffff61212516565b6005546006546040805163858a7c0360e01b8152600481019290925260248201849052519293506001600160a01b039091169163858a7c039160448082019260009290919082900301818387803b15801561131d57600080fd5b505af1158015611331573d6000803e3d6000fd5b5050600d54611349925090508263ffffffff61212516565b600d55600f5461135f908363ffffffff61212516565b600f555090979650505050505050565b611377611715565b61138057600080fd5b61138b8260016129bd565b5060008061139884610aed565b91509150828210156113e6576040805162461bcd60e51b815260206004820152601260248201527109ad2cee4c2e8d2dcce40e8dede40daeac6d60731b604482015290519081900360640190fd5b60006113f0611f1d565b9050600061140883610b36878563ffffffff611f4416565b90506114148682612bb9565b60055460065460408051629ff11560e81b815260048101929092526000888103602484015290516001600160a01b0390931692639ff1150092604480820193929182900301818387803b15801561146a57600080fd5b505af115801561147e573d6000803e3d6000fd5b5050600d54611496925090508663ffffffff61212516565b600d55600480546006546040805163f1382b5360e01b8152938401919091526001600160a01b0389811660248501526044840189905260648401859052905191169163f1382b5391608480830192600092919082900301818387803b1580156114fe57600080fd5b505af1158015611512573d6000803e3d6000fd5b5050600480546006546040805163532e19a960e01b815293840191909152516001600160a01b03909116935063532e19a99250602480830192600092919082900301818387803b15801561156557600080fd5b505af1158015611579573d6000803e3d6000fd5b5050600480546006546040805163302df4df60e11b8152938401919091526001600160a01b038b81166024850152604484018b905290519116935063605be9be9250606480830192600092919082900301818387803b1580156115db57600080fd5b505af11580156115ef573d6000803e3d6000fd5b50505050505050505050565b6001600160a01b031660009081526020819052604090205490565b61161e611715565b61162757600080fd5b60035460405160009161010090046001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a360038054610100600160a81b0319169055565b6005546001600160a01b031681565b60156020908152600092835260408084209091529082529020805460019091015482565b6116b2611715565b6116bb57600080fd5b600e805460ff1916911515919091179055565b6116d9816001612c60565b50565b6016546001600160a01b031681565b60085481565b60105481565b610b576000611f8d565b60035461010090046001600160a01b031690565b60035461010090046001600160a01b0316331490565b600080610cf06001610cf8565b600a5481565b611746611715565b61174f57600080fd5b61175a8260016129bd565b50611767816000846121fa565b505050565b3360008181526001602090815260408083206001600160a01b03871684529091528120549091610a50918590610ba7908663ffffffff61212516565b6117b0611715565b6117b957600080fd5b610b57612d50565b6000610a5083836000612d5c565b6117d7611715565b6117e057600080fd5b6001600160a01b03831661182a576040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015611824573d6000803e3d6000fd5b50611767565b826001600160a01b031663a9059cbb83836040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b15801561188a57600080fd5b505af115801561189e573d6000803e3d6000fd5b505050506040513d60208110156118b457600080fd5b5051611767576040805162461bcd60e51b815260206004820152600c60248201526b111c985a5b8819985a5b195960a21b604482015290519081900360640190fd5b600354600160a81b900460ff1615611946576040805162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481a5b9a5d195960921b604482015290519081900360640190fd5b6003805460ff60a81b1916600160a81b1790556006839055600480546001600160a01b038085166001600160a01b031992831617909255600580549284169290911691909117905561199781612dea565b61199f612685565b5050670de0b6b3a7640000600a555050600e805460ff19166001179055565b6000610a5083836001612d5c565b6017546001600160a01b031681565b610a3f82826001611cde565b6000806119f2611f1d565b905060086006541015611a06579050610a5e565b6010548015611a2857610cc081610b3684600f54611f4490919063ffffffff16565b50919050565b610b576000612e64565b610a3f82826000611003565b60035460ff1681565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b600e5460ff1681565b610b576001612e64565b6000610bb083836001612843565b60136020526000908152604090205481565b610a3f82826001611003565b6116d9816000612c60565b600080611acd612ec9565b60408051623f675f60e91b815233600482015290519192506000916001600160a01b03841691637ecebe00916024808301926020929190829003018186803b158015611b1857600080fd5b505afa158015611b2c573d6000803e3d6000fd5b505050506040513d6020811015611b4257600080fd5b50516005546040805163d505accf60e01b81523360048201526001600160a01b039283166024820152604481018d9052606481018b905260ff8a16608482015260a4810189905260c4810188905290519293509084169163d505accf9160e48082019260009290919082900301818387803b158015611bc057600080fd5b505af1158015611bd4573d6000803e3d6000fd5b505060408051623f675f60e91b815233600482015290516001850193506001600160a01b0386169250637ecebe0091602480820192602092909190829003018186803b158015611c2357600080fd5b505afa158015611c37573d6000803e3d6000fd5b505050506040513d6020811015611c4d57600080fd5b505114611c92576040805162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a59081c195c9b5a5d60921b604482015290519081900360640190fd5b611c9e89896001612843565b9998505050505050505050565b611cb3611715565b611cbc57600080fd5b6116d981612dea565b611ccd611715565b611cd657600080fd5b610b57613043565b600080611cec8585856124b9565b91509150611cf8613447565b50336000908152601260209081526040918290208251808401909352805480845260019091015491830191909152611d36908363ffffffff61213a16565b81526005546040805163900cf0cf60e01b815290516001600160a01b039092169163900cf0cf91600480820192602092909190829003018186803b158015611d7d57600080fd5b505afa158015611d91573d6000803e3d6000fd5b505050506040513d6020811015611da757600080fd5b505160208281019182523360008181526012909252604080832085518155935160019094019390935560048054600654855163f1382b5360e01b8152928301526024820192909252604481018a90526064810187905292516001600160a01b0390911692839263f1382b539260848084019382900301818387803b158015611e2e57600080fd5b505af1158015611e42573d6000803e3d6000fd5b50505050806001600160a01b031663532e19a96006546040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156111dd57600080fd5b6040805162461bcd60e51b8152602060048201526008602482015267191a5cd8589b195960c21b604482015290519081900360640190fd5b600c546000908215610a54576000611edc610a5a565b90508015611f1657611f13611f0682610b36876a084595161401484a00000063ffffffff611f4416565b839063ffffffff61213a16565b91505b5092915050565b600060086006541015611f3257506064610a5e565b506c01431e0fae6d7217caa000000090565b600082611f5357506000610a54565b82820282848281611f6057fe5b0414610bb057600080fd5b6000808211611f7957600080fd5b6000828481611f8457fe5b04949350505050565b611f95613447565b50336000908152601260209081526040808320815180830190925280548252600101549181019190915290611fca8284613052565b3360008181526012602052604080822082815560010182905560048054600654835163302df4df60e11b81529283015260248201949094526044810185905290519394506001600160a01b039092169263605be9be92606480820193929182900301818387803b15801561203d57600080fd5b505af1158015612051573d6000803e3d6000fd5b50505050505050565b6001600160a01b03821661206d57600080fd5b6001600160a01b038316600090815260208190526040902054612096908263ffffffff61212516565b6001600160a01b0380851660009081526020819052604080822093909355908416815220546120cb908263ffffffff61213a16565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008282111561213457600080fd5b50900390565b600082820183811015610bb057600080fd5b6000806121c3600560009054906101000a90046001600160a01b03166001600160a01b0316637ed4b27c6006546040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b1580156121af57600080fd5b505af1158015610acb573d6000803e3d6000fd5b905060006121d184836127c2565b600c8390556001600160a01b038516600090815260136020526040902092909255509050919050565b600061220461335e565b600e5460ff16612254576040805162461bcd60e51b815260206004820152601660248201527511195b1959d85d1a5bdb881a5cc8191a5cd8589b195960521b604482015290519081900360640190fd5b600061225e610c11565b9050600061226a611f1d565b9050600061228283610b36898563ffffffff611f4416565b9050858110156122cd576040805162461bcd60e51b8152602060048201526011602482015270546f6f206d75636820736c69707061676560781b604482015290519081900360640190fd5b6001600160a01b03851660009081526012602052604090205415612327576040805162461bcd60e51b815260206004820152600c60248201526b13db99dbda5b99c8195e1a5d60a21b604482015290519081900360640190fd5b612331858261339f565b61234582610b36858463ffffffff611f4416565b60055460065460408051629ff11560e81b8152600481019290925260248201849052519299506001600160a01b0390911691639ff115009160448082019260009290919082900301818387803b15801561239e57600080fd5b505af11580156123b2573d6000803e3d6000fd5b5050600d546123ca925090508863ffffffff61213a16565b600d55600480546006546040805163c69d057360e01b8152938401919091526001600160a01b038881166024850152604484018b9052606484018590529051911691829163c69d05739160848082019260009290919082900301818387803b15801561243557600080fd5b505af1158015612449573d6000803e3d6000fd5b50505050806001600160a01b031663532e19a96006546040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b15801561249557600080fd5b505af11580156124a9573d6000803e3d6000fd5b50999a9950505050505050505050565b6000806000806124c833610aed565b91509150816000141580156124dd5750868210155b612523576040805162461bcd60e51b8152602060048201526012602482015271151bdbc81b5d58da081c995c5d595cdd195960721b604482015290519081900360640190fd5b600061252d611f1d565b9050600061254583610b368b8563ffffffff611f4416565b905087811115612590576040805162461bcd60e51b8152602060048201526011602482015270746f6f206d75636820736c69707061676560781b604482015290519081900360640190fd5b61259a33886129bd565b506125a53382612bb9565b60055460065460408051629ff11560e81b8152600481019290925260008c8103602484015290516001600160a01b0390931692639ff1150092604480820193929182900301818387803b1580156125fb57600080fd5b505af115801561260f573d6000803e3d6000fd5b5050600d54612627925090508a63ffffffff61212516565b600d5560006126476126376119e7565b610b368c8663ffffffff611f4416565b600f5490915061265d908b63ffffffff61213a16565b600f55601054612673908263ffffffff61213a16565b60105590999098509650505050505050565b6016546000906001600160a01b031680610ae857600560009054906101000a90046001600160a01b03166001600160a01b0316635ab1bd536040518163ffffffff1660e01b815260040160206040518083038186803b1580156126e757600080fd5b505afa1580156126fb573d6000803e3d6000fd5b505050506040513d602081101561271157600080fd5b5051604080516832bb32b73a39a43ab160b91b8152815190819003600901812063cac39a0560e01b8252600482015290516001600160a01b039092169163cac39a0591602480820192602092909190829003018186803b15801561277457600080fd5b505afa158015612788573d6000803e3d6000fd5b505050506040513d602081101561279e57600080fd5b5051601680546001600160a01b0319166001600160a01b0383161790559050905090565b6000806127ce846115fb565b9050806127df576000915050610a54565b6001600160a01b0384166000908152601360205260409020548381141561280b57600092505050610a54565b61283a6a084595161401484a000000610b368461282e888663ffffffff61212516565b9063ffffffff611f4416565b95945050505050565b600061284f33836129bd565b5061285b8484336121fa565b9050816128f15760055460065460408051636901b25360e01b8152600481019290925260248201849052336044830152516001600160a01b0390921691636901b253916064808201926020929091908290030181600087803b1580156128c057600080fd5b505af11580156128d4573d6000803e3d6000fd5b505050506040513d60208110156128ea57600080fd5b505161297b565b60055460065460408051624c025560e81b8152600481019290925260248201849052336044830152516001600160a01b0390921691634c025500916064808201926020929091908290030181600087803b15801561294e57600080fd5b505af1158015612962573d6000803e3d6000fd5b505050506040513d602081101561297857600080fd5b50515b610bb0576040805162461bcd60e51b815260206004820152600e60248201526d19195c1bdcda5d0819985a5b195960921b604482015290519081900360640190fd5b6000806129c98461214c565b90508015610bb05782612a67576005546006546040805163bc8756a960e01b81526004810192909252602482018490526001600160a01b038781166044840152905192169163bc8756a9916064808201926020929091908290030181600087803b158015612a3657600080fd5b505af1158015612a4a573d6000803e3d6000fd5b505050506040513d6020811015612a6057600080fd5b5051612af4565b6005546006546040805163c7f067cb60e01b81526004810192909252602482018490526001600160a01b038781166044840152905192169163c7f067cb916064808201926020929091908290030181600087803b158015612ac757600080fd5b505af1158015612adb573d6000803e3d6000fd5b505050506040513d6020811015612af157600080fd5b50515b612b3b576040805162461bcd60e51b8152602060048201526013602482015272496e737566666963656e74207265776172647360681b604482015290519081900360640190fd5b600480546006546040805163b7721d2d60e01b8152938401919091526001600160a01b03878116602485015260448401859052905191169163b7721d2d91606480830192600092919082900301818387803b158015612b9957600080fd5b505af1158015612bad573d6000803e3d6000fd5b50505050905092915050565b6001600160a01b038216612bcc57600080fd5b600254612bdf908263ffffffff61212516565b6002556001600160a01b038216600090815260208190526040902054612c0b908263ffffffff61212516565b6001600160a01b038316600081815260208181526040808320949094558351858152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35050565b612c68613447565b503360009081526015602090815260408083208584528252808320815180830190925280548252600101549181019190915290612ca58284613052565b3360009081526015602090815260408083208884529091528120818155600101559050612cd0612685565b60065460408051636e699d8760e01b815260048101929092523360248301526044820184905260648201879052516001600160a01b039290921691636e699d879160848082019260009290919082900301818387803b158015612d3257600080fd5b505af1158015612d46573d6000803e3d6000fd5b5050505050505050565b6003805460ff19169055565b33612d6784836129bd565b50612d7281836129bd565b50612d7e81858561205a565b612d86612685565b6006546040805163c08b3f9d60e01b815260048101929092526001600160a01b038481166024840152878116604484015260648301879052905192169163c08b3f9d9160848082019260009290919082900301818387803b158015612d3257600080fd5b6001600160a01b038116612dfd57600080fd5b6003546040516001600160a01b0380841692610100900416907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600380546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6000612e7033836129bd565b9050600a54811015610a3f576040805162461bcd60e51b815260206004820152601860248201527f546f6f20736d616c6c207265776172647320616d6f756e740000000000000000604482015290519081900360640190fd5b6017546000906001600160a01b031680610ae857600560009054906101000a90046001600160a01b03166001600160a01b0316635ab1bd536040518163ffffffff1660e01b815260040160206040518083038186803b158015612f2b57600080fd5b505afa158015612f3f573d6000803e3d6000fd5b505050506040513d6020811015612f5557600080fd5b505160408051621c1bdb60ea1b8152815190819003600301812063cac39a0560e01b8252600482015290516001600160a01b039092169163cac39a0591602480820192602092909190829003018186803b158015612fb257600080fd5b505afa158015612fc6573d6000803e3d6000fd5b505050506040513d6020811015612fdc57600080fd5b505190506001600160a01b038116613023576040805162461bcd60e51b81526020600482015260056024820152641d5b9cd95d60da1b604482015290519081900360640190fd5b601780546001600160a01b0319166001600160a01b038316179055919050565b6003805460ff19166001179055565b81516005546040805163900cf0cf60e01b81529051600093926001600160a01b03169163900cf0cf916004808301926020929190829003018186803b15801561309a57600080fd5b505afa1580156130ae573d6000803e3d6000fd5b505050506040513d60208110156130c457600080fd5b50516005546040805163a7ab696160e01b81529051613149926001600160a01b03169163a7ab6961916004808301926020929190829003018186803b15801561310c57600080fd5b505afa158015613120573d6000803e3d6000fd5b505050506040513d602081101561313657600080fd5b505160208701519063ffffffff61213a16565b111580156131575750600081115b6131a8576040805162461bcd60e51b815260206004820152601c60248201527f496e636f6d706c657465207769746864726177616c20706572696f6400000000604482015290519081900360640190fd5b60006131c16131b5611f1d565b610b368461282e6119e7565b6010549091506131d7908363ffffffff61212516565b601055600f546131ed908263ffffffff61212516565b600f5583613284576005546006546040805163bc8756a960e01b8152600481019290925260248201849052336044830152516001600160a01b039092169163bc8756a9916064808201926020929091908290030181600087803b15801561325357600080fd5b505af1158015613267573d6000803e3d6000fd5b505050506040513d602081101561327d57600080fd5b505161330f565b6005546006546040805163c7f067cb60e01b8152600481019290925260248201849052336044830152516001600160a01b039092169163c7f067cb916064808201926020929091908290030181600087803b1580156132e257600080fd5b505af11580156132f6573d6000803e3d6000fd5b505050506040513d602081101561330c57600080fd5b50515b613356576040805162461bcd60e51b8152602060048201526013602482015272496e737566666963656e74207265776172647360681b604482015290519081900360640190fd5b949350505050565b60035460ff1615610b57576040805162461bcd60e51b81526020600482015260066024820152651b1bd8dad95960d21b604482015290519081900360640190fd5b6001600160a01b0382166133b257600080fd5b6002546133c5908263ffffffff61213a16565b6002556001600160a01b0382166000908152602081905260409020546133f1908263ffffffff61213a16565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b60405180604001604052806000815260200160008152509056fea265627a7a723158204218c2c8b2e87f177283c78647790865bea3a76c3c8e35d83898fc32476d052564736f6c63430005110032", + "nonce": "0x8d", + "chainId": "0xaa36a7" + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "status": "0x1", + "cumulativeGasUsed": "0xcf4a40", + "logs": [ + { + "address": "0x777badc2c75bd4ee5303bf6e90009bd31d8fd3d1", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000724d72eb61e508d81ca701881f2248f092953bf" + ], + "data": "0x", + "blockHash": "0x80bb5b7121caad8c640dafc4e50623df1bc4757fbe8f5cd035bd702d975119ec", + "blockNumber": "0x605f17", + "transactionHash": "0x4499d0ecf70c3a39927d5245cac653c02f0f0c33dc82be6a9ce5d37d4615c70a", + "transactionIndex": "0x40", + "logIndex": "0x73", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000002000001000000000000004000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000020000010000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x4499d0ecf70c3a39927d5245cac653c02f0f0c33dc82be6a9ce5d37d4615c70a", + "transactionIndex": "0x40", + "blockHash": "0x80bb5b7121caad8c640dafc4e50623df1bc4757fbe8f5cd035bd702d975119ec", + "blockNumber": "0x605f17", + "gasUsed": "0x526898", + "effectiveGasPrice": "0x3be653915", + "from": "0x0724d72eb61e508d81ca701881f2248f092953bf", + "to": null, + "contractAddress": "0x777badc2c75bd4ee5303bf6e90009bd31d8fd3d1" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0xfcdd6b", + "logs": [ + { + "address": "0x19b0b3256b22116096a2ef8cafc6e832ba18a947", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000724d72eb61e508d81ca701881f2248f092953bf" + ], + "data": "0x", + "blockHash": "0x80bb5b7121caad8c640dafc4e50623df1bc4757fbe8f5cd035bd702d975119ec", + "blockNumber": "0x605f17", + "transactionHash": "0xae07c932b4a5459bd683767dde161e9fa7ad1cc9b0ac83a39f9c291bcb22b79f", + "transactionIndex": "0x41", + "logIndex": "0x74", + "removed": false + } + ], + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000100100400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000020000010000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0xae07c932b4a5459bd683767dde161e9fa7ad1cc9b0ac83a39f9c291bcb22b79f", + "transactionIndex": "0x41", + "blockHash": "0x80bb5b7121caad8c640dafc4e50623df1bc4757fbe8f5cd035bd702d975119ec", + "blockNumber": "0x605f17", + "gasUsed": "0x2d932b", + "effectiveGasPrice": "0x3be653915", + "from": "0x0724d72eb61e508d81ca701881f2248f092953bf", + "to": null, + "contractAddress": "0x19b0b3256b22116096a2ef8cafc6e832ba18a947" + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1721057742, + "chain": 11155111, + "commit": "a5fd7d69" +} \ No newline at end of file From d36f6abd4e3554c08354a4c89ad8d6ca1e2c5b2f Mon Sep 17 00:00:00 2001 From: Simon Dosch Date: Tue, 16 Jul 2024 13:21:55 +0200 Subject: [PATCH 60/92] fix: upgradeDepositManager script --- .../deployers/pol-upgrade/UpgradeDepositManager_Sepolia.s.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/deployers/pol-upgrade/UpgradeDepositManager_Sepolia.s.sol b/scripts/deployers/pol-upgrade/UpgradeDepositManager_Sepolia.s.sol index e7139f25..0edda2c0 100644 --- a/scripts/deployers/pol-upgrade/UpgradeDepositManager_Sepolia.s.sol +++ b/scripts/deployers/pol-upgrade/UpgradeDepositManager_Sepolia.s.sol @@ -93,10 +93,10 @@ contract UpgradeDepositManager_Sepolia is Script { ERC20 maticToken = ERC20(matic); uint256 amount = maticToken.balanceOf(address(depositManagerProxy)); bytes memory payloadMigrateMatic = abi.encodeWithSelector( - governance.update.selector, registryAddress, abi.encodeWithSelector(depositManager.migrateMatic.selector, amount) + governance.update.selector, address(depositManagerProxy), abi.encodeWithSelector(depositManager.migrateMatic.selector, amount) ); - console.log("\n Send payloadMigrateMatic to: ", address(depositManagerProxy)); + console.log("\n Send payloadMigrateMatic to: ", governanceAddress); console.logBytes(payloadMigrateMatic); } } From 9ec1c71f1b27c834228b7e18415e03b2783996f6 Mon Sep 17 00:00:00 2001 From: Simon Dosch Date: Mon, 22 Jul 2024 12:35:55 +0200 Subject: [PATCH 61/92] feat: burn matic dynamically --- contracts/root/depositManager/DepositManager.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contracts/root/depositManager/DepositManager.sol b/contracts/root/depositManager/DepositManager.sol index 0cf6ac2b..e8322d4e 100644 --- a/contracts/root/depositManager/DepositManager.sol +++ b/contracts/root/depositManager/DepositManager.sol @@ -44,8 +44,9 @@ contract DepositManager is DepositManagerStorage, IDepositManager, ERC721Holder } // new: governance function to migrate MATIC to POL - function migrateMatic(uint256 _amount) external onlyGovernance { - _migrateMatic(_amount); + function migrateMatic(uint256) external onlyGovernance { + IERC20 matic = IERC20(registry.contractMap(keccak256("matic"))); + _migrateMatic(matic.balanceOf(address(this))); } function _migrateMatic(uint256 _amount) private { From 558dc877d5b19b864b44a9e8322a1b51ee0a0292 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Thu, 18 Jul 2024 19:15:22 +0200 Subject: [PATCH 62/92] feat: add mainnet pol upgrade script --- contracts/common/misc/ITimelock.sol | 80 +++++++ .../UpgradeStake_DepositManager_Mainnet.s.sol | 207 ++++++++++++++++++ scripts/deployers/pol-upgrade/input.json | 1 + 3 files changed, 288 insertions(+) create mode 100644 contracts/common/misc/ITimelock.sol create mode 100644 scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol diff --git a/contracts/common/misc/ITimelock.sol b/contracts/common/misc/ITimelock.sol new file mode 100644 index 00000000..b965e9f4 --- /dev/null +++ b/contracts/common/misc/ITimelock.sol @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.4; + +// extracted using cast interface 0xCaf0aa768A3AE1297DF20072419Db8Bb8b5C8cEf + +interface Timelock { + event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data); + event CallScheduled( + bytes32 indexed id, + uint256 indexed index, + address target, + uint256 value, + bytes data, + bytes32 predecessor, + uint256 delay + ); + event Cancelled(bytes32 indexed id); + event MinDelayChange(uint256 oldDuration, uint256 newDuration); + event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); + event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); + event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); + + receive() external payable; + + function DEFAULT_ADMIN_ROLE() external view returns (bytes32); + function EXECUTOR_ROLE() external view returns (bytes32); + function PROPOSER_ROLE() external view returns (bytes32); + function TIMELOCK_ADMIN_ROLE() external view returns (bytes32); + function cancel(bytes32 id) external; + function execute(address target, uint256 value, bytes memory data, bytes32 predecessor, bytes32 salt) + external + payable; + function executeBatch( + address[] memory targets, + uint256[] memory values, + bytes[] memory datas, + bytes32 predecessor, + bytes32 salt + ) external payable; + function getMinDelay() external view returns (uint256 duration); + function getRoleAdmin(bytes32 role) external view returns (bytes32); + function getTimestamp(bytes32 id) external view returns (uint256 timestamp); + function grantRole(bytes32 role, address account) external; + function hasRole(bytes32 role, address account) external view returns (bool); + function hashOperation(address target, uint256 value, bytes memory data, bytes32 predecessor, bytes32 salt) + external + pure + returns (bytes32 hash); + function hashOperationBatch( + address[] memory targets, + uint256[] memory values, + bytes[] memory datas, + bytes32 predecessor, + bytes32 salt + ) external pure returns (bytes32 hash); + function isOperation(bytes32 id) external view returns (bool pending); + function isOperationDone(bytes32 id) external view returns (bool done); + function isOperationPending(bytes32 id) external view returns (bool pending); + function isOperationReady(bytes32 id) external view returns (bool ready); + function renounceRole(bytes32 role, address account) external; + function revokeRole(bytes32 role, address account) external; + function schedule( + address target, + uint256 value, + bytes memory data, + bytes32 predecessor, + bytes32 salt, + uint256 delay + ) external; + function scheduleBatch( + address[] memory targets, + uint256[] memory values, + bytes[] memory datas, + bytes32 predecessor, + bytes32 salt, + uint256 delay + ) external; + function supportsInterface(bytes4 interfaceId) external view returns (bool); + function updateDelay(uint256 newDelay) external; +} diff --git a/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol b/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol new file mode 100644 index 00000000..16f07805 --- /dev/null +++ b/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {Script, stdJson, console} from "forge-std/Script.sol"; + +import {StakeManager} from "../../helpers/interfaces/StakeManager.generated.sol"; +import {StakeManagerProxy} from "../../helpers/interfaces/StakeManagerProxy.generated.sol"; +import {ValidatorShare} from "../../helpers/interfaces/ValidatorShare.generated.sol"; +import {Registry} from "../../helpers/interfaces/Registry.generated.sol"; +import {Governance} from "../../helpers/interfaces/Governance.generated.sol"; +import {DepositManager} from "../../helpers/interfaces/DepositManager.generated.sol"; +import {DepositManagerProxy} from "../../helpers/interfaces/DepositManagerProxy.generated.sol"; +import {ERC20} from "../../helpers/interfaces/ERC20.generated.sol"; + +import {Timelock} from "../../../contracts/common/misc/ITimelock.sol"; + +contract UpgradeStake_DepositManager_Mainnet is Script { + using stdJson for string; + + function run() public { + uint256 deployerPrivateKey = vm.promptSecretUint("Enter deployer private key: "); + + string memory input = vm.readFile("scripts/deployers/pol-upgrade/input.json"); + string memory chainIdSlug = string(abi.encodePacked('["', vm.toString(block.chainid), '"]')); + address registryAddress = input.readAddress(string.concat(chainIdSlug, ".registry")); + address stakeManagerProxyAddress = input.readAddress(string.concat(chainIdSlug, ".stakeManagerProxy")); + address governanceAddress = input.readAddress(string.concat(chainIdSlug, ".governance")); + address polTokenAddress = input.readAddress(string.concat(chainIdSlug, ".polToken")); + address migrationAddress = input.readAddress(string.concat(chainIdSlug, ".migration")); + address timelockAddress = input.readAddress(string.concat(chainIdSlug, ".timelock")); + address payable depositManagerProxyAddress = payable(input.readAddress(string.concat(chainIdSlug, ".depositManagerProxy"))); + address maticAddress = input.readAddress(string.concat(chainIdSlug, ".matic")); + address nativeGasTokenAddress = address(0x0000000000000000000000000000000000001010); + + vm.startBroadcast(deployerPrivateKey); + + // deploy STEP 1 + // deploy new StakeManager version + StakeManager stakeManagerImpl; + stakeManagerImpl = StakeManager(deployCode("out/StakeManager.sol/StakeManager.json")); + + console.log("deployed StakeManager implementation at: ", address(stakeManagerImpl)); + + // deploy STEP 2 + // deploy new ValidatorShare version + ValidatorShare validatorShareImpl; + validatorShareImpl = ValidatorShare(deployCode("out/ValidatorShare.sol/ValidatorShare.json")); + + console.log("deployed ValidatorShare implementation at: ", address(validatorShareImpl)); + + // deploy STEP 3 + // deploy new DepositManager version + DepositManager depositManagerImpl; + depositManagerImpl = DepositManager(payable(deployCode("out/DepositManager.sol/DepositManager.json"))); + + console.log("deployed DepositManager implementation at: ", address(validatorShareImpl)); + + vm.stopBroadcast(); + + Registry registry = Registry(registryAddress); + console.log("using Registry at: ", address(registry)); + + StakeManager stakeManager = StakeManager(stakeManagerProxyAddress); + StakeManagerProxy stakeManagerProxy = StakeManagerProxy(payable(stakeManagerProxyAddress)); + console.log("using StakeManagerProxy at: ", address(stakeManagerProxy)); + + DepositManager depositManager = DepositManager(depositManagerProxyAddress); + DepositManagerProxy depositManagerProxy = DepositManagerProxy(depositManagerProxyAddress); + console.log("using DepositManagerProxy at: ", address(depositManagerProxy)); + + Governance governance = Governance(governanceAddress); + console.log("using Governance at: ", address(governanceAddress)); + + Timelock timelock = Timelock(payable(timelockAddress)); + console.log("using Timelock at: ", address(timelockAddress)); + + ERC20 maticToken = ERC20(maticAddress); + console.log("using Matic at: ", address(maticAddress)); + + console.log("----------------------"); + console.log("Generating payloads \n"); + + // STEP 1 + // Update ValidatorShare registry entry + bytes memory payloadRegistry1 = abi.encodeWithSelector( + governance.update.selector, + address(registry), + abi.encodeWithSelector(registry.updateContractMap.selector, keccak256("validatorShare"), address(validatorShareImpl)) + ); + + console.log("Created payloadRegistry1 for: ", address(governance)); + console.logBytes(payloadRegistry1); + + + // STEP 2 + // Update StakeManagerProxy implementation contract + bytes memory payloadStakeManager2 = abi.encodeWithSelector(stakeManagerProxy.updateImplementation.selector, address(stakeManagerImpl)); + + console.log("Created payloadStakeManager2 for: ", address(stakeManagerProxy)); + console.logBytes(payloadStakeManager2); + + // STEP 3 + // Call initializePOL + bytes memory payloadInitializePol3 = abi.encodeWithSelector( + governance.update.selector, address(stakeManagerProxy), abi.encodeWithSelector(stakeManager.initializePOL.selector, polTokenAddress, migrationAddress) + ); + + console.log("Created payloadInitializePol3 for: ", address(governance)); + console.logBytes(payloadInitializePol3); + + // STEP 4 + // Call updateContractMap on registry to add "pol" + bytes memory payloadContractMapPol4 = abi.encodeWithSelector( + governance.update.selector, address(registry), abi.encodeWithSelector(registry.updateContractMap.selector, keccak256("pol"), polTokenAddress) + ); + + console.log("Send payloadContractMapPol4 to: ", address(governance)); + console.logBytes(payloadContractMapPol4); + + // STEP 5 + // Call updateContractMap on registry to add "matic" + bytes memory payloadContractMapMatic5 = abi.encodeWithSelector( + governance.update.selector, address(registry), abi.encodeWithSelector(registry.updateContractMap.selector, keccak256("matic"), maticAddress) + ); + + console.log("\n Send payloadContractMapMatic5 to: ", address(governance)); + console.logBytes(payloadContractMapMatic5); + + // STEP 6 + // Call updateContractMap on registry to add "polygonMigration" + bytes memory payloadContractMapMigration6 = abi.encodeWithSelector( + governance.update.selector, address(registry), abi.encodeWithSelector(registry.updateContractMap.selector, keccak256("polygonMigration"), migrationAddress) + ); + + console.log("Send payloadContractMapMigration6 to: ", address(governance)); + console.logBytes(payloadContractMapMigration6); + + // STEP 7 + // call mapToken on the Registry to map POL to the PoS native gas token address (1010) + bytes memory payloadMapToken7 = abi.encodeWithSelector( + governance.update.selector, address(registry), abi.encodeWithSelector(registry.mapToken.selector, polTokenAddress, nativeGasTokenAddress, false) + ); + + console.log("Send payloadMapToken7 to: ", address(governance)); + console.logBytes(payloadMapToken7); + + // STEP 8 + // update impl of proxy to DepositManager + bytes memory payloadUpgradeDepositManager8 = abi.encodeWithSelector(depositManagerProxy.updateImplementation.selector, address(depositManagerImpl)); + + console.log(); + console.log("Send payloadUpgradeDepositManager8 to: ", address(depositManagerProxy)); + console.logBytes(payloadUpgradeDepositManager8); + + // STEP 9 + // call migrateMatic on the new DepositManager, migrating all MATIC + uint256 amount = maticToken.balanceOf(address(depositManagerProxy)); + bytes memory payloadMigrateMatic9 = abi.encodeWithSelector( + governance.update.selector, address(depositManagerProxy), abi.encodeWithSelector(depositManager.migrateMatic.selector, amount) + ); + + console.log("\n Send payloadMigrateMatic9 to: ", address(governance)); + console.logBytes(payloadMigrateMatic9); + + console.log("----------------------"); + console.log("Batching payloads \n"); + + address[] memory targets = new address[](9); + targets[0] = address(governance); + targets[1] = address(stakeManagerProxy); + targets[2] = address(governance); + targets[3] = address(governance); + targets[4] = address(governance); + targets[5] = address(governance); + targets[6] = address(governance); + targets[7] = address(depositManagerProxy); + targets[8] = address(governance); + + // Inits to 0 + uint256[] memory values = new uint256[](9); + + bytes[] memory payloads = new bytes[](9); + payloads[0] = payloadRegistry1; + payloads[1] = payloadStakeManager2; + payloads[2] = payloadInitializePol3; + payloads[3] = payloadContractMapPol4; + payloads[4] = payloadContractMapMatic5; + payloads[5] = payloadContractMapMigration6; + payloads[6] = payloadMapToken7; + payloads[7] = payloadUpgradeDepositManager8; + payloads[8] = payloadMigrateMatic9; + + bytes memory batchPayload = abi.encodeWithSelector(Timelock.scheduleBatch.selector, targets, values, payloads, "", ""); + bytes32 payloadId = timelock.hashOperationBatch(targets, values, payloads, "", ""); + + console.log("Expected batch ID: %s", vm.toString(payloadId)); + console.log("Send batchPayload to: ", address(timelock)); + console.logBytes(batchPayload); + + bytes memory executePayload = abi.encodeWithSelector(Timelock.executeBatch.selector, targets, values, payloads, "", ""); + + console.log("----------------------"); + console.log("After at least 7 days send executePayload to: ", address(timelock)); + console.logBytes(executePayload); + + } +} diff --git a/scripts/deployers/pol-upgrade/input.json b/scripts/deployers/pol-upgrade/input.json index 6d26e826..b1cd28d1 100644 --- a/scripts/deployers/pol-upgrade/input.json +++ b/scripts/deployers/pol-upgrade/input.json @@ -6,6 +6,7 @@ "governance": "0x6e7a5820baD6cebA8Ef5ea69c0C92EbbDAc9CE48", "timelock": "0xCaf0aa768A3AE1297DF20072419Db8Bb8b5C8cEf", "polToken": "0x455e53CBB86018Ac2B8092FdCd39d8444aFFC3F6", + "matic": "0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0", "migration": "0x29e7DF7b6A1B2b07b731457f499E1696c60E2C4e" }, "11155111": { From 84e9129e4ae28bbdb2a16c8002bd5c2883a976e1 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Mon, 22 Jul 2024 13:51:04 +0200 Subject: [PATCH 63/92] feat: improve mainnet deploy script --- foundry.toml | 2 +- .../UpgradeStake_DepositManager_Mainnet.s.sol | 153 ++++++++++-------- scripts/deployers/pol-upgrade/input.json | 8 +- 3 files changed, 91 insertions(+), 72 deletions(-) diff --git a/foundry.toml b/foundry.toml index 8dabbfcd..47ef9c57 100644 --- a/foundry.toml +++ b/foundry.toml @@ -8,7 +8,7 @@ optimizer_runs = 200 via_ir = true cache_path = 'forge-cache' verbosity = 2 -# solc_version = '0.5.17' + ffi = true remappings = [ "openzeppelin-solidity/=node_modules/openzeppelin-solidity/", diff --git a/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol b/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol index 16f07805..b37eced6 100644 --- a/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol +++ b/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol @@ -17,92 +17,117 @@ import {Timelock} from "../../../contracts/common/misc/ITimelock.sol"; contract UpgradeStake_DepositManager_Mainnet is Script { using stdJson for string; + Timelock timelock; + Registry registry; + StakeManager stakeManagerProxy; + Governance governance; + ERC20 polToken; + address migrationAddress; + DepositManager depositManagerProxy; + ERC20 maticToken; + address nativeGasTokenAddress; + address gSafeAddress; + function run() public { uint256 deployerPrivateKey = vm.promptSecretUint("Enter deployer private key: "); + //uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + loadConfig(); + (StakeManager stakeManagerImpl, ValidatorShare validatorShareImpl, DepositManager depositManagerImpl) = deployImplementations(deployerPrivateKey); + (bytes memory scheduleBatchPayload, bytes memory executeBatchPayload, bytes32 payloadId) = + createPayload(stakeManagerImpl, validatorShareImpl, depositManagerImpl); + + console.log("Send scheduleBatchPayload to: ", address(timelock)); + console.logBytes(scheduleBatchPayload); + + console.log("----------------------"); + console.log("After at least 7 days send executeBatchPayload to: ", address(timelock)); + console.logBytes(executeBatchPayload); + } + + function loadConfig() public { + console.log("----------------------"); + console.log("Loading config \n"); string memory input = vm.readFile("scripts/deployers/pol-upgrade/input.json"); string memory chainIdSlug = string(abi.encodePacked('["', vm.toString(block.chainid), '"]')); - address registryAddress = input.readAddress(string.concat(chainIdSlug, ".registry")); - address stakeManagerProxyAddress = input.readAddress(string.concat(chainIdSlug, ".stakeManagerProxy")); - address governanceAddress = input.readAddress(string.concat(chainIdSlug, ".governance")); - address polTokenAddress = input.readAddress(string.concat(chainIdSlug, ".polToken")); - address migrationAddress = input.readAddress(string.concat(chainIdSlug, ".migration")); - address timelockAddress = input.readAddress(string.concat(chainIdSlug, ".timelock")); - address payable depositManagerProxyAddress = payable(input.readAddress(string.concat(chainIdSlug, ".depositManagerProxy"))); - address maticAddress = input.readAddress(string.concat(chainIdSlug, ".matic")); - address nativeGasTokenAddress = address(0x0000000000000000000000000000000000001010); + registry = Registry(input.readAddress(string.concat(chainIdSlug, ".registry"))); + stakeManagerProxy = StakeManager(input.readAddress(string.concat(chainIdSlug, ".stakeManagerProxy"))); + governance = Governance(input.readAddress(string.concat(chainIdSlug, ".governance"))); + polToken = ERC20(input.readAddress(string.concat(chainIdSlug, ".polToken"))); + migrationAddress = input.readAddress(string.concat(chainIdSlug, ".migration")); + timelock = Timelock(payable(input.readAddress(string.concat(chainIdSlug, ".timelock")))); + depositManagerProxy = DepositManager(payable(input.readAddress(string.concat(chainIdSlug, ".depositManagerProxy")))); + maticToken = ERC20(input.readAddress(string.concat(chainIdSlug, ".matic"))); + nativeGasTokenAddress = input.readAddress(string.concat(chainIdSlug, ".nativGasToken")); + gSafeAddress = input.readAddress(string.concat(chainIdSlug, ".gSafe")); + + console.log("using Registry at: ", address(registry)); + console.log("using StakeManagerProxy at: ", address(stakeManagerProxy)); + console.log("using DepositManagerProxy at: ", address(depositManagerProxy)); + console.log("using Governance at: ", address(governance)); + console.log("using Timelock at: ", address(timelock)); + console.log("using Matic at: ", address(maticToken)); + console.log("using POL at: ", address(polToken)); + console.log("using PolygonMigration at: ", migrationAddress); + console.log("using NativGasToken at: ", nativeGasTokenAddress); + console.log("using gSafe at: ", gSafeAddress); + } + + function deployImplementations(uint256 deployerPrivateKey) + public + returns (StakeManager stakeManagerImpl, ValidatorShare validatorShareImpl, DepositManager depositManagerImpl) + { vm.startBroadcast(deployerPrivateKey); // deploy STEP 1 // deploy new StakeManager version - StakeManager stakeManagerImpl; stakeManagerImpl = StakeManager(deployCode("out/StakeManager.sol/StakeManager.json")); console.log("deployed StakeManager implementation at: ", address(stakeManagerImpl)); // deploy STEP 2 // deploy new ValidatorShare version - ValidatorShare validatorShareImpl; validatorShareImpl = ValidatorShare(deployCode("out/ValidatorShare.sol/ValidatorShare.json")); console.log("deployed ValidatorShare implementation at: ", address(validatorShareImpl)); // deploy STEP 3 - // deploy new DepositManager version - DepositManager depositManagerImpl; + // deploy new DepositManager version depositManagerImpl = DepositManager(payable(deployCode("out/DepositManager.sol/DepositManager.json"))); console.log("deployed DepositManager implementation at: ", address(validatorShareImpl)); vm.stopBroadcast(); + } - Registry registry = Registry(registryAddress); - console.log("using Registry at: ", address(registry)); - - StakeManager stakeManager = StakeManager(stakeManagerProxyAddress); - StakeManagerProxy stakeManagerProxy = StakeManagerProxy(payable(stakeManagerProxyAddress)); - console.log("using StakeManagerProxy at: ", address(stakeManagerProxy)); - - DepositManager depositManager = DepositManager(depositManagerProxyAddress); - DepositManagerProxy depositManagerProxy = DepositManagerProxy(depositManagerProxyAddress); - console.log("using DepositManagerProxy at: ", address(depositManagerProxy)); - - Governance governance = Governance(governanceAddress); - console.log("using Governance at: ", address(governanceAddress)); - - Timelock timelock = Timelock(payable(timelockAddress)); - console.log("using Timelock at: ", address(timelockAddress)); - - ERC20 maticToken = ERC20(maticAddress); - console.log("using Matic at: ", address(maticAddress)); - + function createPayload(StakeManager stakeManagerImpl, ValidatorShare validatorShareImpl, DepositManager depositManagerImpl) + public + returns (bytes memory scheduleBatchPayload, bytes memory executeBatchPayload, bytes32 payloadId) + { console.log("----------------------"); console.log("Generating payloads \n"); - // STEP 1 + // STEP 1 // Update ValidatorShare registry entry - bytes memory payloadRegistry1 = abi.encodeWithSelector( - governance.update.selector, - address(registry), - abi.encodeWithSelector(registry.updateContractMap.selector, keccak256("validatorShare"), address(validatorShareImpl)) + bytes memory payloadRegistry1 = abi.encodeCall( + governance.update, (address(registry), abi.encodeCall(registry.updateContractMap, (keccak256("validatorShare"), address(validatorShareImpl)))) ); console.log("Created payloadRegistry1 for: ", address(governance)); console.logBytes(payloadRegistry1); - // STEP 2 // Update StakeManagerProxy implementation contract - bytes memory payloadStakeManager2 = abi.encodeWithSelector(stakeManagerProxy.updateImplementation.selector, address(stakeManagerImpl)); + bytes memory payloadStakeManager2 = abi.encodeCall(StakeManagerProxy.updateImplementation, (address(stakeManagerImpl))); console.log("Created payloadStakeManager2 for: ", address(stakeManagerProxy)); console.logBytes(payloadStakeManager2); // STEP 3 // Call initializePOL - bytes memory payloadInitializePol3 = abi.encodeWithSelector( - governance.update.selector, address(stakeManagerProxy), abi.encodeWithSelector(stakeManager.initializePOL.selector, polTokenAddress, migrationAddress) + bytes memory payloadInitializePol3 = abi.encodeCall( + governance.update, (address(stakeManagerProxy), abi.encodeCall(stakeManagerProxy.initializePOL, (address(polToken), migrationAddress))) ); console.log("Created payloadInitializePol3 for: ", address(governance)); @@ -110,26 +135,24 @@ contract UpgradeStake_DepositManager_Mainnet is Script { // STEP 4 // Call updateContractMap on registry to add "pol" - bytes memory payloadContractMapPol4 = abi.encodeWithSelector( - governance.update.selector, address(registry), abi.encodeWithSelector(registry.updateContractMap.selector, keccak256("pol"), polTokenAddress) - ); + bytes memory payloadContractMapPol4 = + abi.encodeCall(governance.update, (address(registry), abi.encodeCall(registry.updateContractMap, (keccak256("pol"), address(polToken))))); console.log("Send payloadContractMapPol4 to: ", address(governance)); console.logBytes(payloadContractMapPol4); // STEP 5 // Call updateContractMap on registry to add "matic" - bytes memory payloadContractMapMatic5 = abi.encodeWithSelector( - governance.update.selector, address(registry), abi.encodeWithSelector(registry.updateContractMap.selector, keccak256("matic"), maticAddress) - ); + bytes memory payloadContractMapMatic5 = + abi.encodeCall(governance.update, (address(registry), abi.encodeCall(registry.updateContractMap, (keccak256("matic"), address(maticToken))))); - console.log("\n Send payloadContractMapMatic5 to: ", address(governance)); + console.log("Send payloadContractMapMatic5 to: ", address(governance)); console.logBytes(payloadContractMapMatic5); // STEP 6 // Call updateContractMap on registry to add "polygonMigration" - bytes memory payloadContractMapMigration6 = abi.encodeWithSelector( - governance.update.selector, address(registry), abi.encodeWithSelector(registry.updateContractMap.selector, keccak256("polygonMigration"), migrationAddress) + bytes memory payloadContractMapMigration6 = abi.encodeCall( + governance.update, (address(registry), abi.encodeCall(registry.updateContractMap, (keccak256("polygonMigration"), migrationAddress))) ); console.log("Send payloadContractMapMigration6 to: ", address(governance)); @@ -137,8 +160,8 @@ contract UpgradeStake_DepositManager_Mainnet is Script { // STEP 7 // call mapToken on the Registry to map POL to the PoS native gas token address (1010) - bytes memory payloadMapToken7 = abi.encodeWithSelector( - governance.update.selector, address(registry), abi.encodeWithSelector(registry.mapToken.selector, polTokenAddress, nativeGasTokenAddress, false) + bytes memory payloadMapToken7 = abi.encodeCall( + governance.update.selector, (address(registry), abi.encodeCall(registry.mapToken, (address(polToken), nativeGasTokenAddress, false))) ); console.log("Send payloadMapToken7 to: ", address(governance)); @@ -146,7 +169,7 @@ contract UpgradeStake_DepositManager_Mainnet is Script { // STEP 8 // update impl of proxy to DepositManager - bytes memory payloadUpgradeDepositManager8 = abi.encodeWithSelector(depositManagerProxy.updateImplementation.selector, address(depositManagerImpl)); + bytes memory payloadUpgradeDepositManager8 = abi.encodeCall(DepositManagerProxy.updateImplementation, (address(depositManagerImpl))); console.log(); console.log("Send payloadUpgradeDepositManager8 to: ", address(depositManagerProxy)); @@ -155,11 +178,10 @@ contract UpgradeStake_DepositManager_Mainnet is Script { // STEP 9 // call migrateMatic on the new DepositManager, migrating all MATIC uint256 amount = maticToken.balanceOf(address(depositManagerProxy)); - bytes memory payloadMigrateMatic9 = abi.encodeWithSelector( - governance.update.selector, address(depositManagerProxy), abi.encodeWithSelector(depositManager.migrateMatic.selector, amount) - ); + bytes memory payloadMigrateMatic9 = + abi.encodeCall(governance.update, (address(depositManagerProxy), abi.encodeCall(depositManagerProxy.migrateMatic, (amount / 2)))); - console.log("\n Send payloadMigrateMatic9 to: ", address(governance)); + console.log("Send payloadMigrateMatic9 to: ", address(governance)); console.logBytes(payloadMigrateMatic9); console.log("----------------------"); @@ -190,18 +212,11 @@ contract UpgradeStake_DepositManager_Mainnet is Script { payloads[7] = payloadUpgradeDepositManager8; payloads[8] = payloadMigrateMatic9; - bytes memory batchPayload = abi.encodeWithSelector(Timelock.scheduleBatch.selector, targets, values, payloads, "", ""); - bytes32 payloadId = timelock.hashOperationBatch(targets, values, payloads, "", ""); - + payloadId = timelock.hashOperationBatch(targets, values, payloads, "", ""); console.log("Expected batch ID: %s", vm.toString(payloadId)); - console.log("Send batchPayload to: ", address(timelock)); - console.logBytes(batchPayload); - - bytes memory executePayload = abi.encodeWithSelector(Timelock.executeBatch.selector, targets, values, payloads, "", ""); - - console.log("----------------------"); - console.log("After at least 7 days send executePayload to: ", address(timelock)); - console.logBytes(executePayload); + // 172800 is minDelay + scheduleBatchPayload = abi.encodeCall(Timelock.scheduleBatch, (targets, values, payloads, "", "", 172_800)); + executeBatchPayload = abi.encodeCall(Timelock.executeBatch, (targets, values, payloads, "", "")); } } diff --git a/scripts/deployers/pol-upgrade/input.json b/scripts/deployers/pol-upgrade/input.json index b1cd28d1..73fd7edd 100644 --- a/scripts/deployers/pol-upgrade/input.json +++ b/scripts/deployers/pol-upgrade/input.json @@ -7,7 +7,9 @@ "timelock": "0xCaf0aa768A3AE1297DF20072419Db8Bb8b5C8cEf", "polToken": "0x455e53CBB86018Ac2B8092FdCd39d8444aFFC3F6", "matic": "0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0", - "migration": "0x29e7DF7b6A1B2b07b731457f499E1696c60E2C4e" + "migration": "0x29e7DF7b6A1B2b07b731457f499E1696c60E2C4e", + "nativGasToken": "0x0000000000000000000000000000000000001010", + "gSafe": "0xFa7D2a996aC6350f4b56C043112Da0366a59b74c" }, "11155111": { "registry": "0xfE92F7c3a701e43d8479738c8844bCc555b9e5CD", @@ -17,6 +19,8 @@ "governance": "0xB7086eda3180c728C1536B35c4d54F6A2B33D6aC", "polToken": "0x44499312f493F62f2DFd3C6435Ca3603EbFCeeBa", "matic": "0x3fd0A53F4Bf853985a95F4Eb3F9C9FDE1F8e2b53", - "migration": "0x3A3B750E7d4d389Bc1d0be20E5D09530F82B9911" + "migration": "0x3A3B750E7d4d389Bc1d0be20E5D09530F82B9911", + "nativGasToken": "0x0000000000000000000000000000000000001010", + "gSafe": "onlyMainnet" } } \ No newline at end of file From 4b2c7b4ae12cd73b2e432071839d9f3d9b7bb409 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Mon, 22 Jul 2024 13:51:38 +0200 Subject: [PATCH 64/92] feat: use deploy script in upgrade forktest --- test/foundry/ForkupgradeStakeManager.t.sol | 72 ++++++++++++---------- 1 file changed, 40 insertions(+), 32 deletions(-) diff --git a/test/foundry/ForkupgradeStakeManager.t.sol b/test/foundry/ForkupgradeStakeManager.t.sol index 1a8e1a88..055fdf58 100644 --- a/test/foundry/ForkupgradeStakeManager.t.sol +++ b/test/foundry/ForkupgradeStakeManager.t.sol @@ -3,61 +3,69 @@ pragma solidity ^0.8.4; import { StakeManager } from "../../scripts/helpers/interfaces/StakeManager.generated.sol"; import { StakeManagerProxy } from "../../scripts/helpers/interfaces/StakeManagerProxy.generated.sol"; import { ValidatorShare } from "../../scripts/helpers/interfaces/ValidatorShare.generated.sol"; +import {DepositManager} from "../../scripts/helpers/interfaces/DepositManager.generated.sol"; import { Registry } from "../../scripts/helpers/interfaces/Registry.generated.sol"; import { ERC20 } from "../../scripts/helpers/interfaces/ERC20.generated.sol"; +import {UpgradeStake_DepositManager_Mainnet} from "../../scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol"; +import {Timelock} from "../../contracts/common/misc/ITimelock.sol"; + import "forge-std/Test.sol"; -contract ForkupgradeStakeManagerTest is Test { +contract ForkupgradeStakeManagerTest is Test, UpgradeStake_DepositManager_Mainnet { uint256 mainnetFork; function setUp() public { mainnetFork = vm.createFork(vm.rpcUrl("mainnet")); + vm.selectFork(mainnetFork); } function test_UpgradeStakeManager() public { - vm.selectFork(mainnetFork); assertEq(vm.activeFork(), mainnetFork); - StakeManager stakeManagerImpl; - stakeManagerImpl = StakeManager(deployCode("out/StakeManager.sol/StakeManager.json")); - - console.log("deployed StakeManager Implementation at: ", address(stakeManagerImpl)); - - ValidatorShare validatorShareImpl; - validatorShareImpl = ValidatorShare(deployCode("out/ValidatorShare.sol/ValidatorShare.json")); + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); - console.log("deployed ValidatorShare Implementation at: ", address(validatorShareImpl)); + loadConfig(); + (StakeManager stakeManagerImpl, ValidatorShare validatorShareImpl, DepositManager depositManagerImpl) = deployImplementations(deployerPrivateKey); + (bytes memory scheduleBatchPayload, bytes memory executeBatchPayload, bytes32 payloadId) = createPayload(stakeManagerImpl, validatorShareImpl, depositManagerImpl); - Registry registry = Registry(0x33a02E6cC863D393d6Bf231B697b82F6e499cA71); - console.log("found Registry at: ", address(registry)); + uint256 balanceStakeManager = maticToken.balanceOf(address(stakeManagerProxy)); + console.log("Initial StakeManager Matic balance: ", balanceStakeManager); + assertNotEq(balanceStakeManager, 0); + uint256 balanceDepositManager = maticToken.balanceOf(address(depositManagerProxy)); + console.log("Initial DepositManager Matic balance: ", balanceDepositManager); + assertNotEq(balanceDepositManager, 0); - StakeManager stakeManager = StakeManager(0x5e3Ef299fDDf15eAa0432E6e66473ace8c13D908); - StakeManagerProxy stakeManagerProxy = StakeManagerProxy(payable(0x5e3Ef299fDDf15eAa0432E6e66473ace8c13D908)); - console.log("found StakeManagerProxy at: ", address(stakeManagerProxy)); + vm.prank(gSafeAddress); + (bool successSchedule, bytes memory dataSchedule) = address(timelock).call(scheduleBatchPayload); + if (successSchedule == false) { + assembly { + revert(add(dataSchedule,32),mload(dataSchedule)) + } + } - address governance = 0x6e7a5820baD6cebA8Ef5ea69c0C92EbbDAc9CE48; - address timelock = 0xCaf0aa768A3AE1297DF20072419Db8Bb8b5C8cEf; - ERC20 polToken = ERC20(0x455e53CBB86018Ac2B8092FdCd39d8444aFFC3F6); - ERC20 maticToken = ERC20(0x7D1AfA7B718fb893dB30A3aBc0Cfc608AaCfeBB0); - address migration = 0x29e7DF7b6A1B2b07b731457f499E1696c60E2C4e; + assertEq(successSchedule, true); + assertEq(timelock.isOperation(payloadId), true); + assertEq(timelock.isOperationPending(payloadId), true); - uint256 balance = maticToken.balanceOf(address(stakeManagerProxy)); - console.log("Matic balance: ", balance); + vm.warp(block.timestamp + 172800); - // prank set registry as 0x6e7a5820baD6cebA8Ef5ea69c0C92EbbDAc9CE48 - vm.prank(governance); - registry.updateContractMap(keccak256("validatorShare"), address(validatorShareImpl)); + assertEq(timelock.isOperationReady(payloadId), true); - // prank set proxyImpl as 0xCaf0aa768A3AE1297DF20072419Db8Bb8b5C8cEf - vm.prank(timelock); - stakeManagerProxy.updateImplementation(address(stakeManagerImpl)); - // prank call initPol with pol 0x455e53CBB86018Ac2B8092FdCd39d8444aFFC3F6 mig 0x29e7DF7b6A1B2b07b731457f499E1696c60E2C4e as 0x6e7a5820baD6cebA8Ef5ea69c0C92EbbDAc9CE48 + vm.prank(gSafeAddress); - vm.prank(governance); - stakeManager.initializePOL(address(polToken), migration); + (bool successExecute, bytes memory dataExecute) = address(timelock).call(executeBatchPayload); + if (successExecute == false) { + assembly { + revert(add(dataExecute,32),mload(dataExecute)) + } + } + assertEq(successExecute, true); + assertEq(timelock.isOperationDone(payloadId), true); assertEq(maticToken.balanceOf(address(stakeManagerProxy)), 0); - assertEq(polToken.balanceOf(address(stakeManagerProxy)), balance); + assertEq(polToken.balanceOf(address(stakeManagerProxy)), balanceStakeManager); + assertEq(maticToken.balanceOf(address(depositManagerProxy)), balanceDepositManager/2); + assertEq(polToken.balanceOf(address(stakeManagerProxy)), balanceDepositManager/2); } } \ No newline at end of file From 49bae81bb0b6386978c2a01b07c39208cfedcfea Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Mon, 22 Jul 2024 13:59:47 +0200 Subject: [PATCH 65/92] fix: remove fun para --- contracts/root/depositManager/DepositManager.sol | 2 +- .../pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/contracts/root/depositManager/DepositManager.sol b/contracts/root/depositManager/DepositManager.sol index e8322d4e..22beaee9 100644 --- a/contracts/root/depositManager/DepositManager.sol +++ b/contracts/root/depositManager/DepositManager.sol @@ -44,7 +44,7 @@ contract DepositManager is DepositManagerStorage, IDepositManager, ERC721Holder } // new: governance function to migrate MATIC to POL - function migrateMatic(uint256) external onlyGovernance { + function migrateMatic() external onlyGovernance { IERC20 matic = IERC20(registry.contractMap(keccak256("matic"))); _migrateMatic(matic.balanceOf(address(this))); } diff --git a/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol b/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol index b37eced6..e5cce2eb 100644 --- a/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol +++ b/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol @@ -161,7 +161,7 @@ contract UpgradeStake_DepositManager_Mainnet is Script { // STEP 7 // call mapToken on the Registry to map POL to the PoS native gas token address (1010) bytes memory payloadMapToken7 = abi.encodeCall( - governance.update.selector, (address(registry), abi.encodeCall(registry.mapToken, (address(polToken), nativeGasTokenAddress, false))) + governance.update, (address(registry), abi.encodeCall(registry.mapToken, (address(polToken), nativeGasTokenAddress, false))) ); console.log("Send payloadMapToken7 to: ", address(governance)); @@ -177,9 +177,8 @@ contract UpgradeStake_DepositManager_Mainnet is Script { // STEP 9 // call migrateMatic on the new DepositManager, migrating all MATIC - uint256 amount = maticToken.balanceOf(address(depositManagerProxy)); bytes memory payloadMigrateMatic9 = - abi.encodeCall(governance.update, (address(depositManagerProxy), abi.encodeCall(depositManagerProxy.migrateMatic, (amount / 2)))); + abi.encodeCall(governance.update, (address(depositManagerProxy), abi.encodeCall(depositManagerProxy.migrateMatic, ()))); console.log("Send payloadMigrateMatic9 to: ", address(governance)); console.logBytes(payloadMigrateMatic9); From 8575015728227e342fe42cb7696f760cca547105 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Mon, 22 Jul 2024 21:18:52 +0200 Subject: [PATCH 66/92] clean --- package.json | 3 ++- .../UpgradeStake_DepositManager_Mainnet.s.sol | 21 +++++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 7c1223c3..8c952be0 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,8 @@ "bor:stop": "cd test-bor-docker && bash stop-docker.sh", "bor:clean": "cd test-bor-docker && bash clean.sh", "upgrade:stakeManager:sepolia": "forge script scripts/deployers/pol-upgrade/UpgradeStakeManager_Sepolia.s.sol --rpc-url sepolia", - "upgrade:depositManager:sepolia": "forge script scripts/deployers/pol-upgrade/UpgradeDepositManager_Sepolia.s.sol --rpc-url sepolia" + "upgrade:depositManager:sepolia": "forge script scripts/deployers/pol-upgrade/UpgradeDepositManager_Sepolia.s.sol --rpc-url sepolia", + "upgrade:pol:mainnet": "forge script scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol --rpc-url mainnet" }, "keywords": [], "author": "Jaynti Kanani , Simon Dosch Date: Mon, 22 Jul 2024 21:19:36 +0200 Subject: [PATCH 67/92] test: extend upgrade forktest --- test/foundry/ForkupgradeStakeManager.t.sol | 40 +++++++++++++++------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/test/foundry/ForkupgradeStakeManager.t.sol b/test/foundry/ForkupgradeStakeManager.t.sol index 055fdf58..6a93eb71 100644 --- a/test/foundry/ForkupgradeStakeManager.t.sol +++ b/test/foundry/ForkupgradeStakeManager.t.sol @@ -1,11 +1,12 @@ pragma solidity ^0.8.4; -import { StakeManager } from "../../scripts/helpers/interfaces/StakeManager.generated.sol"; -import { StakeManagerProxy } from "../../scripts/helpers/interfaces/StakeManagerProxy.generated.sol"; -import { ValidatorShare } from "../../scripts/helpers/interfaces/ValidatorShare.generated.sol"; +import {StakeManager} from "../../scripts/helpers/interfaces/StakeManager.generated.sol"; +import {StakeManagerProxy} from "../../scripts/helpers/interfaces/StakeManagerProxy.generated.sol"; +import {ValidatorShare} from "../../scripts/helpers/interfaces/ValidatorShare.generated.sol"; import {DepositManager} from "../../scripts/helpers/interfaces/DepositManager.generated.sol"; -import { Registry } from "../../scripts/helpers/interfaces/Registry.generated.sol"; -import { ERC20 } from "../../scripts/helpers/interfaces/ERC20.generated.sol"; +import {Registry} from "../../scripts/helpers/interfaces/Registry.generated.sol"; +import {ERC20} from "../../scripts/helpers/interfaces/ERC20.generated.sol"; +import {Proxy} from "../../scripts/helpers/interfaces/Proxy.generated.sol"; import {UpgradeStake_DepositManager_Mainnet} from "../../scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol"; import {Timelock} from "../../contracts/common/misc/ITimelock.sol"; @@ -27,7 +28,8 @@ contract ForkupgradeStakeManagerTest is Test, UpgradeStake_DepositManager_Mainne loadConfig(); (StakeManager stakeManagerImpl, ValidatorShare validatorShareImpl, DepositManager depositManagerImpl) = deployImplementations(deployerPrivateKey); - (bytes memory scheduleBatchPayload, bytes memory executeBatchPayload, bytes32 payloadId) = createPayload(stakeManagerImpl, validatorShareImpl, depositManagerImpl); + (bytes memory scheduleBatchPayload, bytes memory executeBatchPayload, bytes32 payloadId) = + createPayload(stakeManagerImpl, validatorShareImpl, depositManagerImpl); uint256 balanceStakeManager = maticToken.balanceOf(address(stakeManagerProxy)); console.log("Initial StakeManager Matic balance: ", balanceStakeManager); @@ -40,7 +42,7 @@ contract ForkupgradeStakeManagerTest is Test, UpgradeStake_DepositManager_Mainne (bool successSchedule, bytes memory dataSchedule) = address(timelock).call(scheduleBatchPayload); if (successSchedule == false) { assembly { - revert(add(dataSchedule,32),mload(dataSchedule)) + revert(add(dataSchedule, 32), mload(dataSchedule)) } } @@ -48,7 +50,7 @@ contract ForkupgradeStakeManagerTest is Test, UpgradeStake_DepositManager_Mainne assertEq(timelock.isOperation(payloadId), true); assertEq(timelock.isOperationPending(payloadId), true); - vm.warp(block.timestamp + 172800); + vm.warp(block.timestamp + 172_800); assertEq(timelock.isOperationReady(payloadId), true); @@ -57,15 +59,29 @@ contract ForkupgradeStakeManagerTest is Test, UpgradeStake_DepositManager_Mainne (bool successExecute, bytes memory dataExecute) = address(timelock).call(executeBatchPayload); if (successExecute == false) { assembly { - revert(add(dataExecute,32),mload(dataExecute)) + revert(add(dataExecute, 32), mload(dataExecute)) } } assertEq(successExecute, true); assertEq(timelock.isOperationDone(payloadId), true); + // Check migrations happened assertEq(maticToken.balanceOf(address(stakeManagerProxy)), 0); assertEq(polToken.balanceOf(address(stakeManagerProxy)), balanceStakeManager); - assertEq(maticToken.balanceOf(address(depositManagerProxy)), balanceDepositManager/2); - assertEq(polToken.balanceOf(address(stakeManagerProxy)), balanceDepositManager/2); + assertEq(maticToken.balanceOf(address(depositManagerProxy)), 0); + assertEq(polToken.balanceOf(address(depositManagerProxy)), balanceDepositManager); + + // Check Registry values + assertEq(registry.contractMap(keccak256("validatorShare")), address(validatorShareImpl)); + assertEq(registry.contractMap(keccak256("pol")), address(polToken)); + assertEq(registry.contractMap(keccak256("matic")), address(maticToken)); + assertEq(registry.contractMap(keccak256("polygonMigration")), migrationAddress); + assertEq(registry.rootToChildToken(address(polToken)), nativeGasTokenAddress); + assertEq(registry.childToRootToken(nativeGasTokenAddress), address(polToken)); + assertEq(registry.isERC721(address(polToken)), false); + + // Check Proxy implementation addresses + assertEq(Proxy(payable(address(stakeManagerProxy))).implementation(), address(stakeManagerImpl)); + assertEq(Proxy(payable(address(depositManagerProxy))).implementation(), address(depositManagerImpl)); } -} \ No newline at end of file +} From 069c2be5ac22a1da1c7ba2b2c9be5894faa56573 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Tue, 23 Jul 2024 13:51:14 +0200 Subject: [PATCH 68/92] clean: fmt --- .../UpgradeDepositManager_Sepolia.s.sol | 8 ++--- .../UpgradeStakeManager_Sepolia.s.sol | 33 ++++++------------- .../UpgradeStake_DepositManager_Mainnet.s.sol | 3 +- test/foundry/ForkupgradeStakeManager.t.sol | 1 + 4 files changed, 16 insertions(+), 29 deletions(-) diff --git a/scripts/deployers/pol-upgrade/UpgradeDepositManager_Sepolia.s.sol b/scripts/deployers/pol-upgrade/UpgradeDepositManager_Sepolia.s.sol index 0edda2c0..dc1710fb 100644 --- a/scripts/deployers/pol-upgrade/UpgradeDepositManager_Sepolia.s.sol +++ b/scripts/deployers/pol-upgrade/UpgradeDepositManager_Sepolia.s.sol @@ -3,11 +3,12 @@ pragma solidity ^0.8.4; import {Script, stdJson, console2 as console} from "forge-std/Script.sol"; +// These imports get generated by npm run generate:interfaces import {Registry} from "../../helpers/interfaces/Registry.generated.sol"; import {Governance} from "../../helpers/interfaces/Governance.generated.sol"; import {DepositManager} from "../../helpers/interfaces/DepositManager.generated.sol"; import {DepositManagerProxy} from "../../helpers/interfaces/DepositManagerProxy.generated.sol"; -import { ERC20 } from "../../helpers/interfaces/ERC20.generated.sol"; +import {ERC20} from "../../helpers/interfaces/ERC20.generated.sol"; contract UpgradeDepositManager_Sepolia is Script { using stdJson for string; @@ -80,10 +81,7 @@ contract UpgradeDepositManager_Sepolia is Script { DepositManagerProxy depositManagerProxy = DepositManagerProxy(depositManagerProxyAddress); // update proxy - bytes memory payloadUpgradeDepositManager = abi.encodeWithSelector( - depositManagerProxy.updateImplementation.selector, - address(depositManagerImpl) - ); + bytes memory payloadUpgradeDepositManager = abi.encodeWithSelector(depositManagerProxy.updateImplementation.selector, address(depositManagerImpl)); console.log("\n Send payloadUpgradeDepositManager to: ", address(depositManagerProxy)); console.logBytes(payloadUpgradeDepositManager); diff --git a/scripts/deployers/pol-upgrade/UpgradeStakeManager_Sepolia.s.sol b/scripts/deployers/pol-upgrade/UpgradeStakeManager_Sepolia.s.sol index 3978d4ba..b533b02d 100644 --- a/scripts/deployers/pol-upgrade/UpgradeStakeManager_Sepolia.s.sol +++ b/scripts/deployers/pol-upgrade/UpgradeStakeManager_Sepolia.s.sol @@ -3,11 +3,12 @@ pragma solidity ^0.8.4; import {Script, stdJson, console2 as console} from "forge-std/Script.sol"; -import { StakeManager } from "../../helpers/interfaces/StakeManager.generated.sol"; -import { StakeManagerProxy } from "../../helpers/interfaces/StakeManagerProxy.generated.sol"; -import { ValidatorShare } from "../../helpers/interfaces/ValidatorShare.generated.sol"; -import { Registry } from "../../helpers/interfaces/Registry.generated.sol"; -import { Governance } from "../../helpers/interfaces/Governance.generated.sol"; +// These imports get generated by npm run generate:interfaces +import {StakeManager} from "../../helpers/interfaces/StakeManager.generated.sol"; +import {StakeManagerProxy} from "../../helpers/interfaces/StakeManagerProxy.generated.sol"; +import {ValidatorShare} from "../../helpers/interfaces/ValidatorShare.generated.sol"; +import {Registry} from "../../helpers/interfaces/Registry.generated.sol"; +import {Governance} from "../../helpers/interfaces/Governance.generated.sol"; contract UpgradeStakeManager_Sepolia is Script { using stdJson for string; @@ -44,38 +45,24 @@ contract UpgradeStakeManager_Sepolia is Script { vm.stopBroadcast(); - Governance governance = Governance(governanceAddress); bytes memory payloadRegistry = abi.encodeWithSelector( governance.update.selector, address(registry), - abi.encodeWithSelector( - registry.updateContractMap.selector, - keccak256("validatorShare"), - address(validatorShareImpl) - ) + abi.encodeWithSelector(registry.updateContractMap.selector, keccak256("validatorShare"), address(validatorShareImpl)) ); console.log("Send payloadRegistry to: ", address(governance)); console.logBytes(payloadRegistry); - bytes memory payloadStakeManager = abi.encodeWithSelector( - stakeManagerProxy.updateImplementation.selector, - address(stakeManagerImpl) - ); - + bytes memory payloadStakeManager = abi.encodeWithSelector(stakeManagerProxy.updateImplementation.selector, address(stakeManagerImpl)); + console.log("Send payloadStakeManager to: ", address(stakeManagerProxy)); console.logBytes(payloadStakeManager); bytes memory payloadInitializePol = abi.encodeWithSelector( - governance.update.selector, - address(stakeManagerProxy), - abi.encodeWithSelector( - stakeManager.initializePOL.selector, - address(polToken), - migration - ) + governance.update.selector, address(stakeManagerProxy), abi.encodeWithSelector(stakeManager.initializePOL.selector, address(polToken), migration) ); console.log("Send payloadInitializePol to: ", address(governance)); diff --git a/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol b/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol index 4db1ecbd..a49a4414 100644 --- a/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol +++ b/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.4; import {Script, stdJson, console} from "forge-std/Script.sol"; +// These imports get generated by npm run generate:interfaces import {StakeManager} from "../../helpers/interfaces/StakeManager.generated.sol"; import {StakeManagerProxy} from "../../helpers/interfaces/StakeManagerProxy.generated.sol"; import {ValidatorShare} from "../../helpers/interfaces/ValidatorShare.generated.sol"; @@ -31,7 +32,7 @@ contract UpgradeStake_DepositManager_Mainnet is Script { function run() public { uint256 deployerPrivateKey = vm.promptSecretUint("Enter deployer private key: "); //uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); - + loadConfig(); (StakeManager stakeManagerImpl, ValidatorShare validatorShareImpl, DepositManager depositManagerImpl) = deployImplementations(deployerPrivateKey); (bytes memory scheduleBatchPayload, bytes memory executeBatchPayload, bytes32 payloadId) = diff --git a/test/foundry/ForkupgradeStakeManager.t.sol b/test/foundry/ForkupgradeStakeManager.t.sol index 6a93eb71..e2b9bbda 100644 --- a/test/foundry/ForkupgradeStakeManager.t.sol +++ b/test/foundry/ForkupgradeStakeManager.t.sol @@ -1,5 +1,6 @@ pragma solidity ^0.8.4; +// These imports get generated by npm run generate:interfaces import {StakeManager} from "../../scripts/helpers/interfaces/StakeManager.generated.sol"; import {StakeManagerProxy} from "../../scripts/helpers/interfaces/StakeManagerProxy.generated.sol"; import {ValidatorShare} from "../../scripts/helpers/interfaces/ValidatorShare.generated.sol"; From 09e064c47afa0144899c99766ec85d420fbfe7ef Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Tue, 23 Jul 2024 19:40:24 +0200 Subject: [PATCH 69/92] fix: ci coverage --- .github/workflows/ci.yml | 2 +- hardhat.config.cjs | 35 +++++++++++++++---- .../root/DepositManagerUpdate.test.js | 2 +- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e8c4394b..0eb536b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,5 +47,5 @@ jobs: id: build - name: Run Forge tests - run: if test -d test/foundry && find test/foundry -name '*.sol' | grep -q .; then npm run generate:interfaces && forge test -vvv; else echo "No .sol files found in test/foundry directory. Skipping Forge tests."; fi + run: npm run generate:interfaces && forge test -vvv id: test diff --git a/hardhat.config.cjs b/hardhat.config.cjs index ae9d72bd..beab3c53 100644 --- a/hardhat.config.cjs +++ b/hardhat.config.cjs @@ -25,13 +25,36 @@ const baseConfig = { }, }, solidity: { - version: foundryConfig.profile.default.solc_version, - settings: { - optimizer: { - enabled: true, - runs: foundryConfig.profile.default.optimizer_runs, + compilers: [ + { + version: "0.5.4", + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, }, - }, + { + version: "0.5.17", + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + { + version: "0.8.4", + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + ], + }, paths: { sources: "./contracts", diff --git a/test/integration/root/DepositManagerUpdate.test.js b/test/integration/root/DepositManagerUpdate.test.js index 7e24dd78..5ff10cf6 100644 --- a/test/integration/root/DepositManagerUpdate.test.js +++ b/test/integration/root/DepositManagerUpdate.test.js @@ -86,7 +86,7 @@ describe('DepositManagerUpdate @skip-on-coverage', async function () { // call migrateMatic using governance await governance.update( depositManager.address, - depositManager.interface.encodeFunctionData('migrateMatic', [amount.toString()]) + depositManager.interface.encodeFunctionData('migrateMatic') ) // check that MATIC balance has been converted to POL From 32af2e7c146cafb44f7466e54bf00388f43fa915 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Tue, 23 Jul 2024 19:56:23 +0200 Subject: [PATCH 70/92] fix: ci foundry --- test/foundry/ForkupgradeStakeManager.t.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/foundry/ForkupgradeStakeManager.t.sol b/test/foundry/ForkupgradeStakeManager.t.sol index e2b9bbda..0c6d12b9 100644 --- a/test/foundry/ForkupgradeStakeManager.t.sol +++ b/test/foundry/ForkupgradeStakeManager.t.sol @@ -25,10 +25,10 @@ contract ForkupgradeStakeManagerTest is Test, UpgradeStake_DepositManager_Mainne function test_UpgradeStakeManager() public { assertEq(vm.activeFork(), mainnetFork); - uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + Vm.Wallet memory wallet = vm.createWallet("fork wallet"); loadConfig(); - (StakeManager stakeManagerImpl, ValidatorShare validatorShareImpl, DepositManager depositManagerImpl) = deployImplementations(deployerPrivateKey); + (StakeManager stakeManagerImpl, ValidatorShare validatorShareImpl, DepositManager depositManagerImpl) = deployImplementations(wallet.privateKey); (bytes memory scheduleBatchPayload, bytes memory executeBatchPayload, bytes32 payloadId) = createPayload(stakeManagerImpl, validatorShareImpl, depositManagerImpl); From 0f8c9c52d19add497313a98fe935c69df7369bc1 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Tue, 23 Jul 2024 20:24:08 +0200 Subject: [PATCH 71/92] fix: generate interfaces first --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0eb536b0..183656d9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,10 +42,11 @@ jobs: - name: Run Forge build run: | + npm run generate:interfaces forge --version forge build --sizes id: build - name: Run Forge tests - run: npm run generate:interfaces && forge test -vvv + run: forge test -vvv id: test From 15435e8329bce7e7457ca1ab98c9484ac6e4e025 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Tue, 23 Jul 2024 21:44:28 +0200 Subject: [PATCH 72/92] fix: build in script --- scripts/helpers/generateInterfaces.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/helpers/generateInterfaces.sh b/scripts/helpers/generateInterfaces.sh index 41dcc6c8..15311b3b 100755 --- a/scripts/helpers/generateInterfaces.sh +++ b/scripts/helpers/generateInterfaces.sh @@ -6,7 +6,7 @@ create_interface () { cast interface "$file" -n $contract > scripts/helpers/interfaces/$contract.generated.sol } -#forge build +forge build mkdir -p scripts/helpers/interfaces From 6422d25b9c318bc5fce01c75d7e8fad6e1ed30d7 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Tue, 23 Jul 2024 22:13:55 +0200 Subject: [PATCH 73/92] fix: ci build --- scripts/helpers/generateInterfaces.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/helpers/generateInterfaces.sh b/scripts/helpers/generateInterfaces.sh index 15311b3b..c98e4321 100755 --- a/scripts/helpers/generateInterfaces.sh +++ b/scripts/helpers/generateInterfaces.sh @@ -6,7 +6,7 @@ create_interface () { cast interface "$file" -n $contract > scripts/helpers/interfaces/$contract.generated.sol } -forge build +forge compile --skip test script mkdir -p scripts/helpers/interfaces From 22030b4040c72241d29ba1850b98b194b39b79a9 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Tue, 23 Jul 2024 23:12:05 +0200 Subject: [PATCH 74/92] ci: add token --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 183656d9..416e5478 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,5 +48,7 @@ jobs: id: build - name: Run Forge tests + env: + INFURA_TOKEN: ${{ secrets.INFURA_TOKEN }} run: forge test -vvv id: test From 8eb7e37bdd313bcbfbd4466fe4711cbb662557bc Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Wed, 24 Jul 2024 14:01:57 +0200 Subject: [PATCH 75/92] ci: don't run on non pull branches --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 416e5478..ddb058d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,8 +1,8 @@ name: CI on: - push: - branches: [main, dev, feat/*, fix/*] + # push: + # branches: [main, dev, feat/*, fix/*] pull_request: branches: [main, dev] From f6cc0d864dc1f7dacad378301b9c527c10fa03c7 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Wed, 24 Jul 2024 15:24:37 +0200 Subject: [PATCH 76/92] fix: ci and time --- .github/workflows/ci.yml | 4 ++-- .../pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ddb058d3..a7a992b4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,8 +1,8 @@ name: CI on: - # push: - # branches: [main, dev, feat/*, fix/*] + push: + branches: [main, dev] pull_request: branches: [main, dev] diff --git a/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol b/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol index a49a4414..c30e03e5 100644 --- a/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol +++ b/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol @@ -47,7 +47,7 @@ contract UpgradeStake_DepositManager_Mainnet is Script { console.log("\n----------------------\n"); - console.log("After at least 7 days send executeBatchPayload to: ", address(timelock)); + console.log("After at least 2 days send executeBatchPayload to: ", address(timelock)); console.logBytes(executeBatchPayload); } From 39abd8808bcf404726593c3fe10f2bfd4a6e6fea Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Thu, 25 Jul 2024 11:23:40 +0200 Subject: [PATCH 77/92] fix: claimfee now sends pol --- .../staking/stakeManager/StakeManager.sol | 2 +- .../staking/stakeManager/StakeManager.test.js | 30 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 5f3041d7..877ea40f 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -358,7 +358,7 @@ contract StakeManager is totalHeimdallFee = totalHeimdallFee.sub(withdrawAmount); logger.logClaimFee(msg.sender, withdrawAmount); userFeeExit[msg.sender] = accumFeeAmount; - _transferToken(msg.sender, withdrawAmount, false); + _transferToken(msg.sender, withdrawAmount, true); } function totalStakedFor(address user) external view returns (uint256) { diff --git a/test/units/staking/stakeManager/StakeManager.test.js b/test/units/staking/stakeManager/StakeManager.test.js index 70876cdd..631eb83d 100644 --- a/test/units/staking/stakeManager/StakeManager.test.js +++ b/test/units/staking/stakeManager/StakeManager.test.js @@ -1559,8 +1559,8 @@ describe('StakeManager', function (accounts) { runTopUpTests(async function () { await doDeploy.call(this) const mintAmount = web3.utils.toWei('10000') - await this.stakeToken.mint(user, mintAmount) - const stakeTokenUser = this.stakeToken.connect(this.stakeToken.provider.getSigner(user)) + await this.polToken.mint(user, mintAmount) + const stakeTokenUser = this.polToken.connect(this.polToken.provider.getSigner(user)) await stakeTokenUser.approve(this.stakeManager.address, mintAmount.toString()) }, user) }) @@ -1581,7 +1581,7 @@ describe('StakeManager', function (accounts) { beforeEach(doDeploy) it('when user approves less than fee', async function () { - const stakeTokenValidatorUser = this.stakeToken.connect(this.stakeToken.provider.getSigner(validatorUser)) + const stakeTokenValidatorUser = this.polToken.connect(this.polToken.provider.getSigner(validatorUser)) await stakeTokenValidatorUser.approve(this.stakeManager.address, new BN(fee).sub(new BN(1)).toString()) const stakeManagerValidatorUser = this.stakeManager.connect(this.stakeManager.provider.getSigner(validatorUser)) @@ -1716,7 +1716,7 @@ describe('StakeManager', function (accounts) { }) it('balance must increase by fee', async function () { - const newBalance = await this.stakeToken.balanceOf(this.user) + const newBalance = await this.polToken.balanceOf(this.user) assertBigNumberEquality(this.beforeClaimBalance.add(this.claimedFee.toString()), newBalance) }) @@ -1755,7 +1755,7 @@ describe('StakeManager', function (accounts) { this.leaf = createLeafFrom.call(this, this.user, 0) this.fee = firstFeeToClaim this.claimedFee = this.fee - this.beforeClaimBalance = await this.stakeToken.balanceOf(this.user) + this.beforeClaimBalance = await this.polToken.balanceOf(this.user) this.beforeClaimTotalHeimdallFee = await this.stakeManager.totalHeimdallFee() }) @@ -1769,7 +1769,7 @@ describe('StakeManager', function (accounts) { this.leaf = createLeafFrom.call(this, this.user, 0) this.fee = secondFeeToClaim this.claimedFee = secondFeeToClaim.sub(firstFeeToClaim) - this.beforeClaimBalance = await this.stakeToken.balanceOf(this.user) + this.beforeClaimBalance = await this.polToken.balanceOf(this.user) this.beforeClaimTotalHeimdallFee = await this.stakeManager.totalHeimdallFee() }) @@ -1801,7 +1801,7 @@ describe('StakeManager', function (accounts) { before(async function () { this.tree = await feeCheckpoint.call(this, AliceValidatorId, 0, 22) this.leaf = createLeafFrom.call(this, this.user, 0) - this.beforeClaimBalance = await this.stakeToken.balanceOf(this.user) + this.beforeClaimBalance = await this.polToken.balanceOf(this.user) }) it('Bob must fail withdrawing', async function () { @@ -1852,7 +1852,7 @@ describe('StakeManager', function (accounts) { describe('claims 1st time', function () { before(async function () { - this.beforeClaimBalance = await this.stakeToken.balanceOf(this.user) + this.beforeClaimBalance = await this.polToken.balanceOf(this.user) this.tree = this.trees[0] this.fee = firstFee this.leaf = createLeafFrom.call(this, AliceValidatorId, 0) @@ -1867,7 +1867,7 @@ describe('StakeManager', function (accounts) { this.fee = secondFee this.index = 0 this.leaf = createLeafFrom.call(this, this.user, 1) - this.beforeClaimBalance = await this.stakeToken.balanceOf(this.user) + this.beforeClaimBalance = await this.polToken.balanceOf(this.user) }) testAliceClaim() @@ -1897,7 +1897,7 @@ describe('StakeManager', function (accounts) { beforeEach(async function () { this.tree = await feeCheckpoint.call(this, this.validatorId, 0, 22) this.leaf = createLeafFrom.call(this, this.user, 0) - this.beforeClaimBalance = await this.stakeToken.balanceOf(this.user) + this.beforeClaimBalance = await this.polToken.balanceOf(this.user) this.proof = utils.bufferToHex(Buffer.concat(this.tree.getProof(this.leaf))) }) @@ -2109,7 +2109,7 @@ describe('StakeManager', function (accounts) { const polTokenBidder = this.polToken.connect(this.polToken.provider.getSigner(this.bidder)) await polTokenBidder.approve(this.stakeManager.address, mintAmount) - this.bidderBalanceBeforeAuction = await this.stakeToken.balanceOf(this.bidder) + this.bidderBalanceBeforeAuction = await this.polToken.balanceOf(this.bidder) this.totalStakedBeforeAuction = await this.stakeManager.totalStaked() const stakeManagerBidder = this.stakeManager.connect(this.stakeManager.provider.getSigner(this.bidder)) @@ -2145,7 +2145,7 @@ describe('StakeManager', function (accounts) { before(async function () { this.prevValidatorAddr = initialStakers[0].getChecksumAddressString() - this.prevValidatorOldBalance = await this.stakeToken.balanceOf(this.prevValidatorAddr) + this.prevValidatorOldBalance = await this.polToken.balanceOf(this.prevValidatorAddr) this.validator = await this.stakeManager.validators(this.validatorId) this.reward = await this.stakeManager.validatorReward(this.validatorId) @@ -2169,10 +2169,10 @@ describe('StakeManager', function (accounts) { prepareToTest() before(async function () { let restakeAmount = web3.utils.toWei('10000') - await this.stakeToken.mint(this.prevValidatorAddr, restakeAmount) + await this.polToken.mint(this.prevValidatorAddr, restakeAmount) - const stakeTokenValidator = this.stakeToken.connect( - this.stakeToken.provider.getSigner(this.prevValidatorAddr) + const stakeTokenValidator = this.polToken.connect( + this.polToken.provider.getSigner(this.prevValidatorAddr) ) await stakeTokenValidator.approve(this.stakeManager.address, restakeAmount) From 4ba894504997c358811bf8cb0f50e119ae25503a Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 13 Aug 2024 19:24:36 +0530 Subject: [PATCH 78/92] fix: unstake active validators --- contracts/staking/stakeManager/StakeManager.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 877ea40f..d5325adc 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -200,10 +200,12 @@ contract StakeManager is // Housekeeping function. @todo remove later function forceUnstake(uint256 validatorId) external onlyGovernance { + require(validators[validatorId].deactivationEpoch == 0); _unstake(validatorId, currentEpoch, false); } function forceUnstakePOL(uint256 validatorId) external onlyGovernance { + require(validators[validatorId].deactivationEpoch == 0); _unstake(validatorId, currentEpoch, true); } From 4b18cbf812eb7f2921d8f0518e6d3995638f42ec Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 13 Aug 2024 19:36:22 +0530 Subject: [PATCH 79/92] chore: rename to avoid collision with `_unstake(valId,exitEpoch,pol)` method --- contracts/staking/stakeManager/StakeManager.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index d5325adc..ce1a26a3 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -421,14 +421,14 @@ contract StakeManager is } function unstake(uint256 validatorId) external onlyStaker(validatorId) { - _unstake(validatorId, false); + _unstakeValidator(validatorId, false); } function unstakePOL(uint256 validatorId) external onlyStaker(validatorId) { - _unstake(validatorId, true); + _unstakeValidator(validatorId, true); } - function _unstake(uint256 validatorId, bool pol) internal { + function _unstakeValidator(uint256 validatorId, bool pol) internal { require(validatorAuction[validatorId].amount == 0); Status status = validators[validatorId].status; From 364a8c2837ee816ce4b63e620a0c69ebefcdd7c6 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 13 Aug 2024 19:36:58 +0530 Subject: [PATCH 80/92] chore: run ci on feat/* pr --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a7a992b4..470a94c2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,7 @@ on: push: branches: [main, dev] pull_request: - branches: [main, dev] + branches: [main, dev, feat/*] jobs: build: From f62c3c48e8a12b3899b2fc81e1fd998abc95d4bb Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Mon, 19 Aug 2024 15:30:27 +0200 Subject: [PATCH 81/92] fix: still sending amount on migrate matic --- .../deployers/pol-upgrade/UpgradeDepositManager_Sepolia.s.sol | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/deployers/pol-upgrade/UpgradeDepositManager_Sepolia.s.sol b/scripts/deployers/pol-upgrade/UpgradeDepositManager_Sepolia.s.sol index dc1710fb..2e0ac404 100644 --- a/scripts/deployers/pol-upgrade/UpgradeDepositManager_Sepolia.s.sol +++ b/scripts/deployers/pol-upgrade/UpgradeDepositManager_Sepolia.s.sol @@ -88,10 +88,8 @@ contract UpgradeDepositManager_Sepolia is Script { // STEP 4 // call migrateMatic on the new DepositManager, migrating all MATIC - ERC20 maticToken = ERC20(matic); - uint256 amount = maticToken.balanceOf(address(depositManagerProxy)); bytes memory payloadMigrateMatic = abi.encodeWithSelector( - governance.update.selector, address(depositManagerProxy), abi.encodeWithSelector(depositManager.migrateMatic.selector, amount) + governance.update.selector, address(depositManagerProxy), abi.encodeWithSelector(depositManager.migrateMatic.selector) ); console.log("\n Send payloadMigrateMatic to: ", governanceAddress); From 08e71ffd8c19327d0e9e0adec6386797bfd9503d Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Mon, 19 Aug 2024 15:41:16 +0200 Subject: [PATCH 82/92] fix: make disable init clearer --- contracts/staking/stakeManager/StakeManager.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 877ea40f..f06bc38d 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -68,7 +68,9 @@ contract StakeManager is require(validators[validatorId].contractAddress == msg.sender, "Invalid contract address"); } - constructor() public GovernanceLockable(address(0x0)) initializer {} + constructor() public GovernanceLockable(address(0x0)) { + _disableInitializer(); + } function initialize( address _registry, From b025f59b5dd5ddaea5831d072a292c3a90920861 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Mon, 19 Aug 2024 15:50:50 +0200 Subject: [PATCH 83/92] fix: print correct depositManagerImpl address --- .../pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol b/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol index c30e03e5..cf28cccd 100644 --- a/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol +++ b/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol @@ -102,7 +102,7 @@ contract UpgradeStake_DepositManager_Mainnet is Script { // deploy new DepositManager version depositManagerImpl = DepositManager(payable(deployCode("out/DepositManager.sol/DepositManager.json"))); - console.log("deployed DepositManager implementation at: ", address(validatorShareImpl)); + console.log("deployed DepositManager implementation at: ", address(depositManagerImpl)); vm.stopBroadcast(); } From 993fe4861b235a7b520f4f0f6701edb076b29423 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Mon, 19 Aug 2024 15:57:43 +0200 Subject: [PATCH 84/92] fix: make init function ordering clearer --- .../staking/stakeManager/StakeManager.sol | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index f06bc38d..0f3f181e 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -110,6 +110,30 @@ contract StakeManager is delegationEnabled = true; } + function reinitialize( + address _NFTContract, + address _stakingLogger, + address _validatorShareFactory, + address _extensionCode + ) external onlyGovernance initializer { + require(isContract(_extensionCode)); + eventsHub = address(0x0); + extensionCode = _extensionCode; + NFTContract = StakingNFT(_NFTContract); + logger = StakingInfo(_stakingLogger); + validatorShareFactory = ValidatorShareFactory(_validatorShareFactory); + } + + function initializePOL( + address _tokenNew, + address _migration + ) external onlyGovernance initializer { + tokenMatic = IERC20(token); + token = IERC20(_tokenNew); + migration = IPolygonMigration(_migration); + _convertMaticToPOL(tokenMatic.balanceOf(address(this))); + } + function isOwner() public view returns (bool) { address _owner; bytes32 position = keccak256("matic.network.proxy.owner"); @@ -323,30 +347,6 @@ contract StakeManager is _transferToken(destination, amount, true); } - function reinitialize( - address _NFTContract, - address _stakingLogger, - address _validatorShareFactory, - address _extensionCode - ) external onlyGovernance { - require(isContract(_extensionCode)); - eventsHub = address(0x0); - extensionCode = _extensionCode; - NFTContract = StakingNFT(_NFTContract); - logger = StakingInfo(_stakingLogger); - validatorShareFactory = ValidatorShareFactory(_validatorShareFactory); - } - - function initializePOL( - address _tokenNew, - address _migration - ) external onlyGovernance { - tokenMatic = IERC20(token); - token = IERC20(_tokenNew); - migration = IPolygonMigration(_migration); - _convertMaticToPOL(tokenMatic.balanceOf(address(this))); - } - /** Public Methods */ From e33a4b2133e2170198754164682594463a230cfd Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Mon, 19 Aug 2024 16:15:57 +0200 Subject: [PATCH 85/92] fix: disable slashing on validatorshare --- contracts/staking/stakeManager/StakeManager.sol | 2 -- .../staking/validatorShare/ValidatorShare.sol | 17 +---------------- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index 0f3f181e..b04559de 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -1114,8 +1114,6 @@ contract StakeManager is } function _unstake(uint256 validatorId, uint256 exitEpoch, bool pol) internal { - // TODO: if validators unstake and slashed to 0, he will be forced to unstake again - // must think how to handle it correctly _updateRewards(validatorId); uint256 amount = validators[validatorId].amount; diff --git a/contracts/staking/validatorShare/ValidatorShare.sol b/contracts/staking/validatorShare/ValidatorShare.sol index 7665f67b..52116445 100644 --- a/contracts/staking/validatorShare/ValidatorShare.sol +++ b/contracts/staking/validatorShare/ValidatorShare.sol @@ -267,22 +267,7 @@ contract ValidatorShare is IValidatorShare, ERC20NonTradable, OwnableLockable, I uint256 delegatedAmount, uint256 totalAmountToSlash ) external onlyOwner returns (uint256) { - uint256 _withdrawPool = withdrawPool; - uint256 delegationAmount = delegatedAmount.add(_withdrawPool); - if (delegationAmount == 0) { - return 0; - } - // total amount to be slashed from delegation pool (active + inactive) - uint256 _amountToSlash = delegationAmount.mul(totalAmountToSlash).div(validatorStake.add(delegationAmount)); - uint256 _amountToSlashWithdrawalPool = _withdrawPool.mul(_amountToSlash).div(delegationAmount); - - // slash inactive pool - uint256 stakeSlashed = _amountToSlash.sub(_amountToSlashWithdrawalPool); - stakeManager.decreaseValidatorDelegatedAmount(validatorId, stakeSlashed); - activeAmount = activeAmount.sub(stakeSlashed); - - withdrawPool = withdrawPool.sub(_amountToSlashWithdrawalPool); - return _amountToSlash; + revert("Slashing disabled"); } function updateDelegation(bool _delegation) external onlyOwner { From 76632fb9c1debd3c8bd739a8d60aefb9934b270f Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Mon, 19 Aug 2024 16:49:55 +0200 Subject: [PATCH 86/92] fix: restore init behaiviour --- contracts/staking/stakeManager/StakeManager.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index b04559de..68fef49f 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -115,7 +115,7 @@ contract StakeManager is address _stakingLogger, address _validatorShareFactory, address _extensionCode - ) external onlyGovernance initializer { + ) external onlyGovernance { require(isContract(_extensionCode)); eventsHub = address(0x0); extensionCode = _extensionCode; @@ -127,7 +127,7 @@ contract StakeManager is function initializePOL( address _tokenNew, address _migration - ) external onlyGovernance initializer { + ) external onlyGovernance { tokenMatic = IERC20(token); token = IERC20(_tokenNew); migration = IPolygonMigration(_migration); From be3df7f4f873e89754336d990a6e2238d008ac87 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Mon, 19 Aug 2024 18:10:53 +0200 Subject: [PATCH 87/92] fix: consistency in encodeCall --- .../UpgradeStake_DepositManager_Mainnet.s.sol | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol b/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol index cf28cccd..9d249a20 100644 --- a/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol +++ b/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol @@ -118,7 +118,7 @@ contract UpgradeStake_DepositManager_Mainnet is Script { // STEP 1 // Update ValidatorShare registry entry bytes memory payloadRegistry1 = abi.encodeCall( - governance.update, (address(registry), abi.encodeCall(registry.updateContractMap, (keccak256("validatorShare"), address(validatorShareImpl)))) + Governance.update, (address(registry), abi.encodeCall(Registry.updateContractMap, (keccak256("validatorShare"), address(validatorShareImpl)))) ); console.log("Created payloadRegistry1 for: ", address(governance)); @@ -134,7 +134,7 @@ contract UpgradeStake_DepositManager_Mainnet is Script { // STEP 3 // Call initializePOL bytes memory payloadInitializePol3 = abi.encodeCall( - governance.update, (address(stakeManagerProxy), abi.encodeCall(stakeManagerProxy.initializePOL, (address(polToken), migrationAddress))) + Governance.update, (address(stakeManagerProxy), abi.encodeCall(StakeManagerProxy.initializePOL, (address(polToken), migrationAddress))) ); console.log("Created payloadInitializePol3 for: ", address(governance)); @@ -143,7 +143,7 @@ contract UpgradeStake_DepositManager_Mainnet is Script { // STEP 4 // Call updateContractMap on registry to add "pol" bytes memory payloadContractMapPol4 = - abi.encodeCall(governance.update, (address(registry), abi.encodeCall(registry.updateContractMap, (keccak256("pol"), address(polToken))))); + abi.encodeCall(Governance.update, (address(registry), abi.encodeCall(Registry.updateContractMap, (keccak256("pol"), address(polToken))))); console.log("Send payloadContractMapPol4 to: ", address(governance)); console.logBytes(payloadContractMapPol4); @@ -151,7 +151,7 @@ contract UpgradeStake_DepositManager_Mainnet is Script { // STEP 5 // Call updateContractMap on registry to add "matic" bytes memory payloadContractMapMatic5 = - abi.encodeCall(governance.update, (address(registry), abi.encodeCall(registry.updateContractMap, (keccak256("matic"), address(maticToken))))); + abi.encodeCall(Governance.update, (address(registry), abi.encodeCall(Registry.updateContractMap, (keccak256("matic"), address(maticToken))))); console.log("Send payloadContractMapMatic5 to: ", address(governance)); console.logBytes(payloadContractMapMatic5); @@ -159,7 +159,7 @@ contract UpgradeStake_DepositManager_Mainnet is Script { // STEP 6 // Call updateContractMap on registry to add "polygonMigration" bytes memory payloadContractMapMigration6 = abi.encodeCall( - governance.update, (address(registry), abi.encodeCall(registry.updateContractMap, (keccak256("polygonMigration"), migrationAddress))) + Governance.update, (address(registry), abi.encodeCall(Registry.updateContractMap, (keccak256("polygonMigration"), migrationAddress))) ); console.log("Send payloadContractMapMigration6 to: ", address(governance)); @@ -168,7 +168,7 @@ contract UpgradeStake_DepositManager_Mainnet is Script { // STEP 7 // call mapToken on the Registry to map POL to the PoS native gas token address (1010) bytes memory payloadMapToken7 = - abi.encodeCall(governance.update, (address(registry), abi.encodeCall(registry.mapToken, (address(polToken), nativeGasTokenAddress, false)))); + abi.encodeCall(Governance.update, (address(registry), abi.encodeCall(Registry.mapToken, (address(polToken), nativeGasTokenAddress, false)))); console.log("Send payloadMapToken7 to: ", address(governance)); console.logBytes(payloadMapToken7); @@ -183,7 +183,7 @@ contract UpgradeStake_DepositManager_Mainnet is Script { // STEP 9 // call migrateMatic on the new DepositManager, migrating all MATIC bytes memory payloadMigrateMatic9 = - abi.encodeCall(governance.update, (address(depositManagerProxy), abi.encodeCall(depositManagerProxy.migrateMatic, ()))); + abi.encodeCall(Governance.update, (address(depositManagerProxy), abi.encodeCall(DepositManagerProxy.migrateMatic, ()))); console.log("Send payloadMigrateMatic9 to: ", address(governance)); console.logBytes(payloadMigrateMatic9); From bce13533d930217468f1f2dd2748208554a77a78 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 20 Aug 2024 15:37:30 +0530 Subject: [PATCH 88/92] test: non-idempotentcy of forceUnstake --- .../stakeManager/StakeManager.Staking.js | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/test/units/staking/stakeManager/StakeManager.Staking.js b/test/units/staking/stakeManager/StakeManager.Staking.js index 29187610..63a0b9bc 100644 --- a/test/units/staking/stakeManager/StakeManager.Staking.js +++ b/test/units/staking/stakeManager/StakeManager.Staking.js @@ -410,6 +410,58 @@ describe('unstake', function () { }) }) + describe('forceUnstake cannot only unstake active validators', function () { + const AliceWallet = wallets[1] + const others = [wallets[2], wallets[3]] + + before(async function() { + await freshDeploy.call(this, true) + }) + before(doStake(AliceWallet)) + before(doStake(others[0])) + before(doStake(others[1])) + before('Alice is forceUnstaked', async function () { + this.validatorId = await this.stakeManager.getValidatorId(AliceWallet.getAddressString()) + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('forceUnstake', [this.validatorId]) + ) + this.lastSyncedEpoch = await this.stakeManager.currentEpoch() + await checkPoint(others, this.rootChainOwner, this.stakeManager) + }) + it('Alice is unstaked', async function () { + const { deactivationEpoch } = await this.stakeManager.validators(this.validatorId) + assertBigNumberEquality(deactivationEpoch, this.lastSyncedEpoch) + }) + it('Alice cannot be forceUnstaked again', async function () { + await expectRevert(this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('forceUnstake', [this.validatorId]) + ), 'Update failed') + }) + it('Alice cannot be forceUnstaked after claiming', async function () { + const endEpoch = this.lastSyncedEpoch.add(await this.stakeManager.WITHDRAWAL_DELAY()) + // mock for i ... range(delay) checkPoint() + await this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('setCurrentEpoch', [endEpoch]) + ) + + await this.stakeManager + .connect(this.stakeManager.provider.getSigner(AliceWallet.getAddressString())) + .unstakeClaim(this.validatorId) + await checkPoint(others, this.rootChainOwner, this.stakeManager) + + await expectRevert( + this.governance.update( + this.stakeManager.address, + this.stakeManager.interface.encodeFunctionData('forceUnstake', [this.validatorId]) + ), + 'Update failed' + ) + }) + }) + describe('when user unstakes right after stake', async function () { const user = wallets[2].getChecksumAddressString() const amounts = walletAmounts[wallets[2].getAddressString()] From bd17618c0d0bcbcb5d14d1ad8d9f7eb53384aa0e Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 20 Aug 2024 15:40:05 +0530 Subject: [PATCH 89/92] test: make robust --- test/units/staking/stakeManager/StakeManager.Staking.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/units/staking/stakeManager/StakeManager.Staking.js b/test/units/staking/stakeManager/StakeManager.Staking.js index 63a0b9bc..da71b106 100644 --- a/test/units/staking/stakeManager/StakeManager.Staking.js +++ b/test/units/staking/stakeManager/StakeManager.Staking.js @@ -444,7 +444,7 @@ describe('unstake', function () { // mock for i ... range(delay) checkPoint() await this.governance.update( this.stakeManager.address, - this.stakeManager.interface.encodeFunctionData('setCurrentEpoch', [endEpoch]) + this.stakeManager.interface.encodeFunctionData('setCurrentEpoch', [endEpoch + 1]) ) await this.stakeManager From 97cb2ef464762e7d80a947c3aab610f6278d6299 Mon Sep 17 00:00:00 2001 From: DhairyaSethi <55102840+DhairyaSethi@users.noreply.github.com> Date: Tue, 20 Aug 2024 15:43:26 +0530 Subject: [PATCH 90/92] fix: move check internally to cover for dethroneAndUnstake --- contracts/staking/stakeManager/StakeManager.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contracts/staking/stakeManager/StakeManager.sol b/contracts/staking/stakeManager/StakeManager.sol index ce1a26a3..5132ffd8 100644 --- a/contracts/staking/stakeManager/StakeManager.sol +++ b/contracts/staking/stakeManager/StakeManager.sol @@ -200,12 +200,10 @@ contract StakeManager is // Housekeeping function. @todo remove later function forceUnstake(uint256 validatorId) external onlyGovernance { - require(validators[validatorId].deactivationEpoch == 0); _unstake(validatorId, currentEpoch, false); } function forceUnstakePOL(uint256 validatorId) external onlyGovernance { - require(validators[validatorId].deactivationEpoch == 0); _unstake(validatorId, currentEpoch, true); } @@ -1114,6 +1112,7 @@ contract StakeManager is } function _unstake(uint256 validatorId, uint256 exitEpoch, bool pol) internal { + require(validators[validatorId].deactivationEpoch == 0); // TODO: if validators unstake and slashed to 0, he will be forced to unstake again // must think how to handle it correctly _updateRewards(validatorId); From f4a5924fe35af6e2faf40f5bbe76928a2a468c84 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Tue, 20 Aug 2024 13:36:00 +0200 Subject: [PATCH 91/92] feat: improve readme --- README.md | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index b2047add..182ed875 100644 --- a/README.md +++ b/README.md @@ -4,19 +4,20 @@ Ethereum smart contracts that power the [Matic Network](https://polygon.technology/polygon-pos). +## Development ### Install dependencies with ``` npm install ``` -### Setup +### Setup git hooks ``` pre-commit install ``` -### Compile +### Prepare templates ``` npm run template:process -- --bor-chain-id 15001 @@ -27,7 +28,30 @@ bor-chain-id should be: Mainnet = 137 TestnetV4 (Mumbai) = 80001 -### Main chain and side chain +### Generate interfaces + +``` +npm run generate:interfaces +``` + +### Build + +``` +forge build +``` + +## Testing + +### Run forge upgrade forktest + +``` +forge test +``` + +### Run unit tests + + +#### Main chain and side chain - Main chain @@ -51,7 +75,7 @@ npm run bor:stop npm run bor:clean ``` -### Run tests +#### Run tests Run Hardhat test @@ -59,12 +83,6 @@ Run Hardhat test npm test:hardhat ``` -Run Foundry test - -``` -npm test:foundry -``` - ### Coverage Run coverage with From f0bdac8473124efb8024417fe61f1753f9a0ccb2 Mon Sep 17 00:00:00 2001 From: ethyla <36268899+ethyla@users.noreply.github.com> Date: Tue, 20 Aug 2024 13:36:18 +0200 Subject: [PATCH 92/92] fix: wrong interface --- .../UpgradeStake_DepositManager_Mainnet.s.sol | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol b/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol index 9d249a20..b4e481db 100644 --- a/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol +++ b/scripts/deployers/pol-upgrade/UpgradeStake_DepositManager_Mainnet.s.sol @@ -134,7 +134,7 @@ contract UpgradeStake_DepositManager_Mainnet is Script { // STEP 3 // Call initializePOL bytes memory payloadInitializePol3 = abi.encodeCall( - Governance.update, (address(stakeManagerProxy), abi.encodeCall(StakeManagerProxy.initializePOL, (address(polToken), migrationAddress))) + Governance.update, (address(stakeManagerProxy), abi.encodeCall(StakeManager.initializePOL, (address(polToken), migrationAddress))) ); console.log("Created payloadInitializePol3 for: ", address(governance)); @@ -145,7 +145,7 @@ contract UpgradeStake_DepositManager_Mainnet is Script { bytes memory payloadContractMapPol4 = abi.encodeCall(Governance.update, (address(registry), abi.encodeCall(Registry.updateContractMap, (keccak256("pol"), address(polToken))))); - console.log("Send payloadContractMapPol4 to: ", address(governance)); + console.log("Created payloadContractMapPol4 for: ", address(governance)); console.logBytes(payloadContractMapPol4); // STEP 5 @@ -153,7 +153,7 @@ contract UpgradeStake_DepositManager_Mainnet is Script { bytes memory payloadContractMapMatic5 = abi.encodeCall(Governance.update, (address(registry), abi.encodeCall(Registry.updateContractMap, (keccak256("matic"), address(maticToken))))); - console.log("Send payloadContractMapMatic5 to: ", address(governance)); + console.log("Created payloadContractMapMatic5 for: ", address(governance)); console.logBytes(payloadContractMapMatic5); // STEP 6 @@ -162,7 +162,7 @@ contract UpgradeStake_DepositManager_Mainnet is Script { Governance.update, (address(registry), abi.encodeCall(Registry.updateContractMap, (keccak256("polygonMigration"), migrationAddress))) ); - console.log("Send payloadContractMapMigration6 to: ", address(governance)); + console.log("Created payloadContractMapMigration6 for: ", address(governance)); console.logBytes(payloadContractMapMigration6); // STEP 7 @@ -170,22 +170,22 @@ contract UpgradeStake_DepositManager_Mainnet is Script { bytes memory payloadMapToken7 = abi.encodeCall(Governance.update, (address(registry), abi.encodeCall(Registry.mapToken, (address(polToken), nativeGasTokenAddress, false)))); - console.log("Send payloadMapToken7 to: ", address(governance)); + console.log("Created payloadMapToken7 for: ", address(governance)); console.logBytes(payloadMapToken7); // STEP 8 // update impl of proxy to DepositManager bytes memory payloadUpgradeDepositManager8 = abi.encodeCall(DepositManagerProxy.updateImplementation, (address(depositManagerImpl))); - console.log("Send payloadUpgradeDepositManager8 to: ", address(depositManagerProxy)); + console.log("Created payloadUpgradeDepositManager8 for: ", address(depositManagerProxy)); console.logBytes(payloadUpgradeDepositManager8); // STEP 9 // call migrateMatic on the new DepositManager, migrating all MATIC bytes memory payloadMigrateMatic9 = - abi.encodeCall(Governance.update, (address(depositManagerProxy), abi.encodeCall(DepositManagerProxy.migrateMatic, ()))); + abi.encodeCall(Governance.update, (address(depositManagerProxy), abi.encodeCall(DepositManager.migrateMatic, ()))); - console.log("Send payloadMigrateMatic9 to: ", address(governance)); + console.log("Created payloadMigrateMatic9 for: ", address(governance)); console.logBytes(payloadMigrateMatic9); console.log("----------------------");