solidity gringotts#26
Conversation
b7a63b2 to
fb4afc8
Compare
|
|
||
| function _coinAmountToWei(IDistribution.Coin memory coin) internal pure returns (uint256) { | ||
| return coin.amount / DECIMAL_USEI_PER_WEI; | ||
| } |
There was a problem hiding this comment.
Reward conversion ignores coin decimals field
Low Severity
_coinAmountToWei divides coin.amount by the hardcoded DECIMAL_USEI_PER_WEI (1e6) without consulting coin.decimals or coin.denom. This produces the correct result only when the precompile returns usei with exactly 18-decimal precision. If the distribution precompile ever returns a coin with a different decimals value or a non-usei denomination, the conversion silently produces an incorrect result, leading to over- or under-counting of staking rewards in all reward-tracking paths.
Reviewed by Cursor Bugbot for commit 2d4e958. Configure here.
PR SummaryHigh Risk Overview Introduces Reviewed by Cursor Bugbot for commit 34219da. Bugbot is set up for automated code reviews on this repo. Configure here. |
| if (!success) revert TransferFailed(); | ||
|
|
||
| emit UnlockedWithdrawn(unlockDistributionAddress, vestedAmount); | ||
| } |
There was a problem hiding this comment.
Vesting withdrawal can consume banked staking rewards
Medium Severity
initiateWithdrawUnlocked sends vestedAmount from the contract balance without accounting for bankedStakingRewards. When the liquid principal (balance minus banked rewards) is less than the requested vesting withdrawal — e.g. because some principal was staked — the transfer consumes SEI that belongs to banked staking rewards, routing those funds to unlockDistributionAddress instead of stakingRewardAddress. The corresponding _calculateWithdrawnRewards later returns less (capped by the now-reduced balance), so the reward address permanently loses that amount. initiateWithdrawReward correctly protects principal via min(bankedStakingRewards, balance), but initiateWithdrawUnlocked has no symmetric guard.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit c6d172a. Configure here.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
There are 4 total unresolved issues (including 2 from previous reviews).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 34219da. Configure here.
|
|
||
| function _calculateWithdrawnRewards() internal view returns (uint256) { | ||
| uint256 bankBalance = address(this).balance; | ||
| return bankedStakingRewards < bankBalance ? bankedStakingRewards : bankBalance; |
There was a problem hiding this comment.
Banked rewards miss implicit balance
Medium Severity
initiateWithdrawReward only forwards min(bankedStakingRewards, balance) via _calculateWithdrawnRewards, while the CosmWasm port derives banked rewards as contract balance minus principal reserved for vesting, staking, and unbonding. Reward wei that sits in the contract without updating bankedStakingRewards can remain stuck after initiateWithdrawReward.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit 34219da. Configure here.
| if (!success) revert DistributionFailed(); | ||
|
|
||
| if (stakingRewardWithdrawAddressConfigured) { | ||
| _recordWithdrawnStakingRewards(pendingRewards); |
There was a problem hiding this comment.
Undelegate banks returned principal
Low Severity
When stakingRewardWithdrawAddressConfigured is true, reward withdrawals add pre-query withdrawableRewards or pendingRewards to withdrawnStakingRewards without checking that those wei actually left the distribution module to stakingRewardAddress, so accounting can exceed rewards truly paid out.
Reviewed by Cursor Bugbot for commit 34219da. Configure here.


Summary
Ports the CosmWasm Gringotts vesting contract to Solidity for deployment on Sei's EVM. Uses native SEI tokens and integrates directly with Sei's staking and distribution precompiles.
Key Features
msg.valueduring deployment0x1005) and distribution (0x1007) precompilesChanges
New Files:
solidity/contracts/Gringotts.sol- Main upgradeable vesting contractsolidity/contracts/GringottsFactory.sol- Factory for deploying proxy instancessolidity/interfaces/IStaking.sol- Sei staking precompile interfacesolidity/interfaces/IDistribution.sol- Sei distribution precompile interfacesolidity/contracts/mocks/- Mock contracts for testingsolidity/scripts/migration/- Migration scripts for CosmWasm → Soliditysolidity/test/Gringotts.test.js- Test suite (15 passing)Configuration:
solidity/package.json- Hardhat project with dependenciessolidity/hardhat.config.js- Compiler settings (0.8.24, viaIR, Sei networks).gitignore- Addednode_modules/and**/cacheUpgrade Process
Contract upgrades require multi-sig admin approval:
proposeUpgrade(newImplementation)voteProposal(proposalId)processProposal(proposalId)Migration from CosmWasm
Export existing contract state
node scripts/migration/export-cosmwasm.js sei1contract... --output export.json
Convert addresses (sei1... → 0x...)
seid q evm sei-addr sei1admin...
Deploy to Sei EVM
EXPORT_FILE=export.json npx hardhat run scripts/migration/deploy-from-export.js --network sei
Note
High Risk
High risk because this introduces new upgradeable Solidity contracts that custody and transfer native SEI, interact with Sei staking/distribution/gov precompiles, and implement admin-controlled upgrade/emergency-withdraw flows.
Overview
Adds a new
solidity/Hardhat project implementing Gringotts as an upgradeable (UUPS) native-SEI vesting contract with admin multi-sig proposals, operator-only staking actions, reward withdrawals via Sei precompiles, and an admin-approved emergency withdrawal path.Introduces
GringottsFactoryfor deploying initialized ERC1967 proxies, Sei precompile interfaces (IStaking,IDistribution,IGov), and mock precompile contracts for testing; adds docs and deployment/migration scripts.Wires up CI via a new
SolidityGitHub Actions workflow tonpm ci, compile, and run tests (with a Sei docker image), updates.gitignorefor Node artifacts, and bumps the Rust crate version to0.1.11.Reviewed by Cursor Bugbot for commit 2d4e958. Bugbot is set up for automated code reviews on this repo. Configure here.