MineFlop runs a single contract, TulpeaYieldVault. It's the Tulpea vault audited by Shieldify: an ERC-4626 vault behind a UUPS proxy, written in Solidity 0.8.24 on OpenZeppelin 5.4.0. We changed a few lines so it fits a pool whose money leaves to pay for GPUs.
#What it does
deposit(assets, receiver) takes USDC and mints usdFLOP, the vault share. Deposits stop when the vault is paused, in emergency shutdown, or past the deposit limit.
usdFLOP has 12 decimals: USDC's 6 plus a 6-decimal offset that protects against inflation attacks. So 1 USDC mints 10¹² units, which the app shows as 1 usdFLOP.
usdFLOP only moves when it's minted or burned. Every transfer reverts:
function _update(address from, address to, uint256 value) internal virtual override {
if (from != address(0) && to != address(0)) revert TransfersDisabled();
super._update(from, to, value);
}There is no USDC exit either. requestRedeem always reverts with RedeemsDisabled(), because depositors are paid in FLOP. The original redeem logic stays in an internal function, so an upgrade could turn it back on.
#How the money leaves
The owner is the team Safe, and the Safe is also the vault's only strategy. Moving USDC to it takes two calls and a day of waiting:
requestDeploy(safe, amount)emitsDeploymentRequestedwith the unlock time.- After
DEPLOYMENT_DELAY(24 hours),executeDeploy(id)sends the USDC to the Safe.
During those 24 hours anyone can watch the request on chain, and the owner can call cancelDeploy. The owner can also pause the vault, change the deposit limit and upgrade the implementation. Ownership changes are two-step.
The Safe can take every deposited USDC. That is how the pool pays for GPUs. The timelock makes every move visible a day ahead, but it doesn't stop one.
#What we changed
| Change | Why |
|---|---|
Transfers blocked in _update |
Points can't be gamed by moving usdFLOP |
requestRedeem reverts |
Payouts are in FLOP, not USDC |
addStrategy no longer calls totalAssets() on the target |
A Safe doesn't implement it |
executeDeploy and idleBalance reserve only claimable withdrawals |
Pending redeem requests can't block funding |
withdrawFromStrategy pulls with transferFrom |
The Safe approves the vault, then the vault pulls |
| Avon and RealEstate strategies deleted | Not used here |
The changes come with a differential audit report in the contracts repo: unit tests, fuzzing (Medusa), mutation testing, Slither and Aderyn. A Shieldify re-review of the changes is planned before mainnet.
#Addresses
| Contract | Address |
|---|---|
| Vault (proxy) | 0x96C8e749218f49F1B2D352adf680f0188252EFd7↗ |
| Vault implementation | 0x5CDc7270218e71Ce614BD4b2CC743feA52dF0371↗ |
| USDC (Circle testnet) | 0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238↗ |
On Sepolia the owner is a deployer wallet, not a Safe.
Coming soon. The addresses will be listed here when the vault is deployed.