Detailed description of the impact of this finding.
I've identified an instance of integer overflow and underflow within the purchase, calculateFunding, settle, calculatePnl and roundUp functions in the PerpetualAtlanticVault contract.
This flaw enables me to manipulate the uint256 value in a way that results in its reduction to zero or inflation to maximum value.
Consequently, I can exploit this situation to make a deposits, withdrawals and transfers exceeding my actual balance.
Proof of Concept
Provide direct links to all referenced code in GitHub.
Lines of code
https://github.com/code-423n4/2023-08-dopex/blob/0ea4387a4851cd6c8811dfb61da95a677f3f63ae/contracts/perp-vault/PerpetualAtlanticVault.sol#L302 https://github.com/code-423n4/2023-08-dopex/blob/0ea4387a4851cd6c8811dfb61da95a677f3f63ae/contracts/perp-vault/PerpetualAtlanticVault.sol#L336 https://github.com/code-423n4/2023-08-dopex/blob/0ea4387a4851cd6c8811dfb61da95a677f3f63ae/contracts/perp-vault/PerpetualAtlanticVault.sol#L445 https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/perp-vault/PerpetualAtlanticVault.sol#L270 https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/perp-vault/PerpetualAtlanticVault.sol#L283 https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/perp-vault/PerpetualAtlanticVault.sol#L427 https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/perp-vault/PerpetualAtlanticVault.sol#L559 https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/perp-vault/PerpetualAtlanticVault.sol#L581
Vulnerability details
Impact
Detailed description of the impact of this finding. I've identified an instance of integer overflow and underflow within the purchase, calculateFunding, settle, calculatePnl and roundUp functions in the PerpetualAtlanticVault contract. This flaw enables me to manipulate the uint256 value in a way that results in its reduction to zero or inflation to maximum value. Consequently, I can exploit this situation to make a deposits, withdrawals and transfers exceeding my actual balance.
Proof of Concept
Provide direct links to all referenced code in GitHub.
Add screenshots, logs, or any other relevant proof that illustrates the concept.
Foundry Exploit
Test Case
Log Foundry
Running 1 test for tests/perp-vault/Integration.t.sol:Integration [PASS] testIntegration() (gas: 1151275) Traces: [12377876] Integration::setUp() ├─ [0] VM::createFork(https://arbitrum-mainnet.infura.io/v3/c088bb4e4cc643d5a0d3bb668a400685, 24023149 [2.402e7]) │ └─ ← 0 ├─ [0] VM::selectFork(0) │ └─ ← () ├─ [1580887] → new MockToken@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f │ ├─ emit RoleGranted(role: 0x0000000000000000000000000000000000000000000000000000000000000000, account: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], sender: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496]) │ ├─ emit RoleGranted(role: 0x9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6, account: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], sender: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496]) │ ├─ emit RoleGranted(role: 0x65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a, account: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], sender: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496]) │ └─ ← 6284 bytes of code ├─ [78729] → new MockStakingStrategy@0x2e234DAe75C793f67A35089C9d99245E1C58470b │ └─ ← 393 bytes of code ├─ [31681] → new MockVolatilityOracle@0xF62849F9A0B5Bf2913b396098F7c7019b51A820a │ └─ ← 158 bytes of code ├─ [37887] → new MockOptionPricing@0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9 │ └─ ← 189 bytes of code ├─ [391598] → new MockRdpxEthPriceOracle@0xc7183455a4C133Ae270771860664b6B7ec320bB1 │ └─ ← 1735 bytes of code ├─ [1580887] → new MockToken@0xa0Cb889707d426A7A386870A03bc70d1b0697598 │ ├─ emit RoleGranted(role: 0x0000000000000000000000000000000000000000000000000000000000000000, account: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], sender: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496]) │ ├─ emit RoleGranted(role: 0x9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6, account: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], sender: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496]) │ ├─ emit RoleGranted(role: 0x65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a, account: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], sender: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496]) │ └─ ← 6284 bytes of code ├─ [3802550] → new PerpetualAtlanticVault@0x1d1499e622D69689cdf9004d05Ec547d650Ff211 │ ├─ [1283] MockToken::symbol() [staticcall] │ │ └─ ← WETH │ ├─ [223] MockToken::decimals() [staticcall] │ │ └─ ← 18 │ ├─ emit RoleGranted(role: 0x0000000000000000000000000000000000000000000000000000000000000000, account: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], sender: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496]) │ ├─ emit RoleGranted(role: 0x241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b08, account: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], sender: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496]) │ └─ ← 17701 bytes of code ├─ [1621781] → new PerpetualAtlanticVaultLP@0xA4AD4f68d0b91CFD19687c881e50f3A00242828c │ ├─ [223] MockToken::decimals() [staticcall] │ │ └─ ← 18 │ ├─ [24681] MockToken::approve(PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ │ ├─ emit Approval(owner: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], spender: PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], amount: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ │ └─ ← true │ ├─ [24681] MockToken::approve(PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ │ ├─ emit Approval(owner: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], spender: PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], amount: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ │ └─ ← true │ └─ ← 7052 bytes of code ├─ [187992] PerpetualAtlanticVault::setAddresses(MockOptionPricing: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9], MockRdpxEthPriceOracle: [0xc7183455a4C133Ae270771860664b6B7ec320bB1], MockVolatilityOracle: [0xF62849F9A0B5Bf2913b396098F7c7019b51A820a], 0x0000000000000000000000000000000000000001, MockToken: [0xa0Cb889707d426A7A386870A03bc70d1b0697598], PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496]) │ ├─ [2826] MockToken::allowance(PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c]) [staticcall] │ │ └─ ← 0 │ ├─ [22581] MockToken::approve(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ │ ├─ emit Approval(owner: PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], spender: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], amount: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ │ └─ ← true │ ├─ emit AddressesSet(addresses: (0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9, 0xc7183455a4C133Ae270771860664b6B7ec320bB1, 0xF62849F9A0B5Bf2913b396098F7c7019b51A820a, 0x0000000000000000000000000000000000000001, 0xa0Cb889707d426A7A386870A03bc70d1b0697598, 0xA4AD4f68d0b91CFD19687c881e50f3A00242828c, 0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496)) │ └─ ← () ├─ [295] PerpetualAtlanticVault::RDPXV2CORE_ROLE() [staticcall] │ └─ ← 0xaf2ff2efa3cad65457fb5a76d1a146cc0c5db93bb8aa443da1e53a495bcd0533 ├─ [27615] PerpetualAtlanticVault::grantRole(0xaf2ff2efa3cad65457fb5a76d1a146cc0c5db93bb8aa443da1e53a495bcd0533, Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496]) │ ├─ emit RoleGranted(role: 0xaf2ff2efa3cad65457fb5a76d1a146cc0c5db93bb8aa443da1e53a495bcd0533, account: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], sender: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496]) │ └─ ← () ├─ [47193] MockToken::mint(Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], 2000000000000000000000 [2e21]) │ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], amount: 2000000000000000000000 [2e21]) │ └─ ← () ├─ [47193] MockToken::mint(Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], 200000000000000000000 [2e20]) │ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], amount: 200000000000000000000 [2e20]) │ └─ ← () ├─ [3393] MockToken::mint(Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], 3000000000000000000000 [3e21]) │ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], amount: 3000000000000000000000 [3e21]) │ └─ ← () ├─ [2040372] 0xc35DADB65012eC5796536bD9864eD8773aBc74C4::createPair(MockToken: [0xa0Cb889707d426A7A386870A03bc70d1b0697598], MockToken: [0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f]) │ ├─ [1884378] → new@0x67BB1854eEba34B4C6F9459424b182A4F30b72b1
│ │ └─ ← 9079 bytes of code
│ ├─ [44728] 0x67BB1854eEba34B4C6F9459424b182A4F30b72b1::initialize(MockToken: [0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f], MockToken: [0xa0Cb889707d426A7A386870A03bc70d1b0697598])
│ │ └─ ← ()
│ ├─ emit topic 0: 0x0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9
│ │ topic 1: 0x0000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f
│ │ topic 2: 0x000000000000000000000000a0cb889707d426a7a386870a03bc70d1b0697598
│ │ data: 0x00000000000000000000000067bb1854eeba34b4c6f9459424b182a4f30b72b10000000000000000000000000000000000000000000000000000000000000453
│ └─ ← 0x00000000000000000000000067bb1854eeba34b4c6f9459424b182a4f30b72b1
├─ [24681] MockToken::approve(0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506, 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])
│ ├─ emit Approval(owner: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], spender: 0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506, amount: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])
│ └─ ← true
├─ [24681] MockToken::approve(0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506, 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])
│ ├─ emit Approval(owner: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], spender: 0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506, amount: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])
│ └─ ← true
├─ [24681] MockToken::approve(PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])
│ ├─ emit Approval(owner: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], spender: PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], amount: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])
│ └─ ← true
├─ [24681] MockToken::approve(PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])
│ ├─ emit Approval(owner: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], spender: PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], amount: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])
│ └─ ← true
├─ [24681] MockToken::approve(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])
│ ├─ emit Approval(owner: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], spender: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], amount: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])
│ └─ ← true
├─ [24681] MockToken::approve(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])
│ ├─ emit Approval(owner: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], spender: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], amount: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])
│ └─ ← true
├─ [195622] 0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506::addLiquidity(MockToken: [0xa0Cb889707d426A7A386870A03bc70d1b0697598], MockToken: [0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f], 1000000000000000000000 [1e21], 200000000000000000000 [2e20], 100000000000000000000 [1e20], 200000000000000000000 [2e20], 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38, 1662865216 [1.662e9])
│ ├─ [644] 0xc35DADB65012eC5796536bD9864eD8773aBc74C4::getPair(MockToken: [0xa0Cb889707d426A7A386870A03bc70d1b0697598], MockToken: [0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f]) [staticcall]
│ │ └─ ← 0x00000000000000000000000067bb1854eeba34b4c6f9459424b182a4f30b72b1
│ ├─ [2517] 0x67BB1854eEba34B4C6F9459424b182A4F30b72b1::getReserves() [staticcall]
│ │ └─ ← 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
│ ├─ [25701] MockToken::transferFrom(Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], 0x67BB1854eEba34B4C6F9459424b182A4F30b72b1, 1000000000000000000000 [1e21])
│ │ ├─ emit Transfer(from: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], to: 0x67BB1854eEba34B4C6F9459424b182A4F30b72b1, amount: 1000000000000000000000 [1e21])
│ │ └─ ← true
│ ├─ [25701] MockToken::transferFrom(Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], 0x67BB1854eEba34B4C6F9459424b182A4F30b72b1, 200000000000000000000 [2e20])
│ │ ├─ emit Transfer(from: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], to: 0x67BB1854eEba34B4C6F9459424b182A4F30b72b1, amount: 200000000000000000000 [2e20])
│ │ └─ ← true
│ ├─ [134863] 0x67BB1854eEba34B4C6F9459424b182A4F30b72b1::mint(0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38)
│ │ ├─ [583] MockToken::balanceOf(0x67BB1854eEba34B4C6F9459424b182A4F30b72b1) [staticcall]
│ │ │ └─ ← 200000000000000000000 [2e20]
│ │ ├─ [583] MockToken::balanceOf(0x67BB1854eEba34B4C6F9459424b182A4F30b72b1) [staticcall]
│ │ │ └─ ← 1000000000000000000000 [1e21]
│ │ ├─ [2338] 0xc35DADB65012eC5796536bD9864eD8773aBc74C4::feeTo() [staticcall]
│ │ │ └─ ← 0x000000000000000000000000a19b3b22f29e23e4c04678c94cfc3e8f202137d8
│ │ ├─ [2337] 0xc35DADB65012eC5796536bD9864eD8773aBc74C4::migrator() [staticcall]
│ │ │ └─ ← 0x0000000000000000000000000000000000000000000000000000000000000000
│ │ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: 0x0000000000000000000000000000000000000000, amount: 1000)
│ │ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38, amount: 447213595499957938281 [4.472e20])
│ │ ├─ emit Sync(: 200000000000000000000 [2e20], : 1000000000000000000000 [1e21])
│ │ ├─ emit Mint(param0: 0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506, param1: 200000000000000000000 [2e20], param2: 1000000000000000000000 [1e21])
│ │ └─ ← 0x0000000000000000000000000000000000000000000000183e55dbab04396869
│ └─ ← 0x00000000000000000000000000000000000000000000003635c9adc5dea0000000000000000000000000000000000000000000000000000ad78ebc5ac62000000000000000000000000000000000000000000000000000183e55dbab04396869
├─ [24488] PerpetualAtlanticVault::addToContractWhitelist(Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496])
│ ├─ emit AddToContractWhitelist(_contract: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496])
│ └─ ← ()
├─ [844] PerpetualAtlanticVault::updateFundingDuration(86400 [8.64e4])
│ └─ ← ()
├─ [357] MockRdpxEthPriceOracle::updateRdpxPrice(20000000 [2e7])
│ └─ ← ()
└─ ← ()
[1151275] Integration::testIntegration() ├─ [0] VM::startPrank(0x0000000000000000000000000000000000000001, 0x0000000000000000000000000000000000000001) │ └─ ← () ├─ [24681] MockToken::approve(PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ ├─ emit Approval(owner: 0x0000000000000000000000000000000000000001, spender: PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], amount: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ └─ ← true ├─ [24681] MockToken::approve(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ ├─ emit Approval(owner: 0x0000000000000000000000000000000000000001, spender: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], amount: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ └─ ← true ├─ [24681] MockToken::approve(PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ ├─ emit Approval(owner: 0x0000000000000000000000000000000000000001, spender: PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], amount: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ └─ ← true ├─ [24681] MockToken::approve(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ ├─ emit Approval(owner: 0x0000000000000000000000000000000000000001, spender: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], amount: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ └─ ← true ├─ [0] VM::stopPrank() │ └─ ← () ├─ [0] VM::startPrank(0x0000000000000000000000000000000000000002, 0x0000000000000000000000000000000000000002) │ └─ ← () ├─ [24681] MockToken::approve(PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ ├─ emit Approval(owner: 0x0000000000000000000000000000000000000002, spender: PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], amount: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ └─ ← true ├─ [24681] MockToken::approve(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ ├─ emit Approval(owner: 0x0000000000000000000000000000000000000002, spender: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], amount: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ └─ ← true ├─ [24681] MockToken::approve(PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ ├─ emit Approval(owner: 0x0000000000000000000000000000000000000002, spender: PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], amount: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ └─ ← true ├─ [24681] MockToken::approve(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ ├─ emit Approval(owner: 0x0000000000000000000000000000000000000002, spender: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], amount: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ └─ ← true ├─ [0] VM::stopPrank() │ └─ ← () ├─ [0] VM::startPrank(0x0000000000000000000000000000000000000003, 0x0000000000000000000000000000000000000003) │ └─ ← () ├─ [24681] MockToken::approve(PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ ├─ emit Approval(owner: 0x0000000000000000000000000000000000000003, spender: PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], amount: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ └─ ← true ├─ [24681] MockToken::approve(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ ├─ emit Approval(owner: 0x0000000000000000000000000000000000000003, spender: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], amount: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ └─ ← true ├─ [24681] MockToken::approve(PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ ├─ emit Approval(owner: 0x0000000000000000000000000000000000000003, spender: PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], amount: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ └─ ← true ├─ [24681] MockToken::approve(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ ├─ emit Approval(owner: 0x0000000000000000000000000000000000000003, spender: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], amount: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77]) │ └─ ← true ├─ [0] VM::stopPrank() │ └─ ← () ├─ [34093] MockToken::mint(0x0000000000000000000000000000000000000001, 5000000000000000000 [5e18]) │ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: 0x0000000000000000000000000000000000000001, amount: 5000000000000000000 [5e18]) │ └─ ← () ├─ [25293] MockToken::mint(0x0000000000000000000000000000000000000002, 20000000000000000000 [2e19]) │ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: 0x0000000000000000000000000000000000000002, amount: 20000000000000000000 [2e19]) │ └─ ← () ├─ [25293] MockToken::mint(0x0000000000000000000000000000000000000003, 25000000000000000000 [2.5e19]) │ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: 0x0000000000000000000000000000000000000003, amount: 25000000000000000000 [2.5e19]) │ └─ ← () ├─ [0] VM::startPrank(0x0000000000000000000000000000000000000001, 0x0000000000000000000000000000000000000001) │ └─ ← () ├─ [143192] PerpetualAtlanticVaultLP::deposit(5000000000000000000 [5e18], 0x0000000000000000000000000000000000000001) │ ├─ [7644] PerpetualAtlanticVault::getUnderlyingPrice() [staticcall] │ │ ├─ [2324] MockRdpxEthPriceOracle::getRdpxPriceInEth() [staticcall] │ │ │ └─ ← 20000000 [2e7] │ │ └─ ← 20000000 [2e7] │ ├─ [51946] PerpetualAtlanticVault::updateFunding() │ │ ├─ [7315] MockToken::transfer(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], 0) │ │ │ ├─ emit Transfer(from: PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], to: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], amount: 0) │ │ │ └─ ← true │ │ ├─ [4031] PerpetualAtlanticVaultLP::addProceeds(0) │ │ │ ├─ [583] MockToken::balanceOf(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c]) [staticcall] │ │ │ │ └─ ← 0 │ │ │ └─ ← () │ │ ├─ emit FundingPaid(sender: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], amount: 0, latestFundingPaymentPointer: 0) │ │ └─ ← () │ ├─ [18961] MockToken::transferFrom(0x0000000000000000000000000000000000000001, PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], 5000000000000000000 [5e18]) │ │ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000001, to: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], amount: 5000000000000000000 [5e18]) │ │ └─ ← true │ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: 0x0000000000000000000000000000000000000001, amount: 5000000000000000000 [5e18]) │ ├─ emit Deposit(caller: 0x0000000000000000000000000000000000000001, owner: 0x0000000000000000000000000000000000000001, assets: 5000000000000000000 [5e18], shares: 5000000000000000000 [5e18]) │ └─ ← 0x0000000000000000000000000000000000000000000000004563918244f40000 ├─ [0] VM::stopPrank() │ └─ ← () ├─ [0] VM::startPrank(0x0000000000000000000000000000000000000002, 0x0000000000000000000000000000000000000002) │ └─ ← () ├─ [36826] PerpetualAtlanticVaultLP::deposit(20000000000000000000 [2e19], 0x0000000000000000000000000000000000000002) │ ├─ [1144] PerpetualAtlanticVault::getUnderlyingPrice() [staticcall] │ │ ├─ [324] MockRdpxEthPriceOracle::getRdpxPriceInEth() [staticcall] │ │ │ └─ ← 20000000 [2e7] │ │ └─ ← 20000000 [2e7] │ ├─ [11472] PerpetualAtlanticVault::updateFunding() │ │ ├─ [3315] MockToken::transfer(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], 0) │ │ │ ├─ emit Transfer(from: PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], to: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], amount: 0) │ │ │ └─ ← true │ │ ├─ [2031] PerpetualAtlanticVaultLP::addProceeds(0) │ │ │ ├─ [583] MockToken::balanceOf(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c]) [staticcall] │ │ │ │ └─ ← 5000000000000000000 [5e18] │ │ │ └─ ← () │ │ ├─ emit FundingPaid(sender: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], amount: 0, latestFundingPaymentPointer: 0) │ │ └─ ← () │ ├─ [3041] MockToken::transferFrom(0x0000000000000000000000000000000000000002, PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], 20000000000000000000 [2e19]) │ │ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000002, to: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], amount: 20000000000000000000 [2e19]) │ │ └─ ← true │ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: 0x0000000000000000000000000000000000000002, amount: 20000000000000000000 [2e19]) │ ├─ emit Deposit(caller: 0x0000000000000000000000000000000000000002, owner: 0x0000000000000000000000000000000000000002, assets: 20000000000000000000 [2e19], shares: 20000000000000000000 [2e19]) │ └─ ← 0x000000000000000000000000000000000000000000000001158e460913d00000 ├─ [0] VM::stopPrank() │ └─ ← () ├─ [0] VM::startPrank(0x0000000000000000000000000000000000000003, 0x0000000000000000000000000000000000000003) │ └─ ← () ├─ [36826] PerpetualAtlanticVaultLP::deposit(25000000000000000000 [2.5e19], 0x0000000000000000000000000000000000000003) │ ├─ [1144] PerpetualAtlanticVault::getUnderlyingPrice() [staticcall] │ │ ├─ [324] MockRdpxEthPriceOracle::getRdpxPriceInEth() [staticcall] │ │ │ └─ ← 20000000 [2e7] │ │ └─ ← 20000000 [2e7] │ ├─ [11472] PerpetualAtlanticVault::updateFunding() │ │ ├─ [3315] MockToken::transfer(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], 0) │ │ │ ├─ emit Transfer(from: PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], to: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], amount: 0) │ │ │ └─ ← true │ │ ├─ [2031] PerpetualAtlanticVaultLP::addProceeds(0) │ │ │ ├─ [583] MockToken::balanceOf(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c]) [staticcall] │ │ │ │ └─ ← 25000000000000000000 [2.5e19] │ │ │ └─ ← () │ │ ├─ emit FundingPaid(sender: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], amount: 0, latestFundingPaymentPointer: 0) │ │ └─ ← () │ ├─ [3041] MockToken::transferFrom(0x0000000000000000000000000000000000000003, PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], 25000000000000000000 [2.5e19]) │ │ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000003, to: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], amount: 25000000000000000000 [2.5e19]) │ │ └─ ← true │ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: 0x0000000000000000000000000000000000000003, amount: 25000000000000000000 [2.5e19]) │ ├─ emit Deposit(caller: 0x0000000000000000000000000000000000000003, owner: 0x0000000000000000000000000000000000000003, assets: 25000000000000000000 [2.5e19], shares: 25000000000000000000 [2.5e19]) │ └─ ← 0x0000000000000000000000000000000000000000000000015af1d78b58c40000 ├─ [0] VM::stopPrank() │ └─ ← () ├─ [564] PerpetualAtlanticVaultLP::balanceOf(0x0000000000000000000000000000000000000001) [staticcall] │ └─ ← 5000000000000000000 [5e18] ├─ [564] PerpetualAtlanticVaultLP::balanceOf(0x0000000000000000000000000000000000000002) [staticcall] │ └─ ← 20000000000000000000 [2e19] ├─ [564] PerpetualAtlanticVaultLP::balanceOf(0x0000000000000000000000000000000000000003) [staticcall] │ └─ ← 25000000000000000000 [2.5e19] ├─ [0] VM::startPrank(Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496]) │ └─ ← () ├─ [354946] PerpetualAtlanticVault::purchase(100000000000000000000 [1e20], Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496]) │ ├─ [3315] MockToken::transfer(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], 0) │ │ ├─ emit Transfer(from: PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], to: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], amount: 0) │ │ └─ ← true │ ├─ [2031] PerpetualAtlanticVaultLP::addProceeds(0) │ │ ├─ [583] MockToken::balanceOf(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c]) [staticcall] │ │ │ └─ ← 50000000000000000000 [5e19] │ │ └─ ← () │ ├─ emit FundingPaid(sender: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], amount: 0, latestFundingPaymentPointer: 0) │ ├─ [324] MockRdpxEthPriceOracle::getRdpxPriceInEth() [staticcall] │ │ └─ ← 20000000 [2e7] │ ├─ [2583] PerpetualAtlanticVaultLP::totalAvailableCollateral() [staticcall] │ │ └─ ← 50000000000000000000 [5e19] │ ├─ [324] MockRdpxEthPriceOracle::getRdpxPriceInEth() [staticcall] │ │ └─ ← 20000000 [2e7] │ ├─ [240] MockVolatilityOracle::getVolatility(15000000 [1.5e7]) [staticcall] │ │ └─ ← 100 │ ├─ [309] MockOptionPricing::getOptionPrice(15000000 [1.5e7], 20000000 [2e7], 100, 86400 [8.64e4]) [staticcall] │ │ └─ ← 5000000 [5e6] │ ├─ [30501] MockToken::transferFrom(Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], 5000000000000000000 [5e18]) │ │ ├─ emit Transfer(from: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], to: PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], amount: 5000000000000000000 [5e18]) │ │ └─ ← true │ ├─ [20607] PerpetualAtlanticVaultLP::lockCollateral(15000000000000000000 [1.5e19]) │ │ └─ ← () │ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], tokenId: 0) │ ├─ emit Purchase(strike: 15000000 [1.5e7], amount: 100000000000000000000 [1e20], premium: 5000000000000000000 [5e18], to: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], sender: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496]) │ └─ ← 5000000000000000000 [5e18] ├─ [0] VM::stopPrank() │ └─ ← () ├─ [358] PerpetualAtlanticVaultLP::activeCollateral() [staticcall] │ └─ ← 15000000000000000000 [1.5e19] ├─ [385] PerpetualAtlanticVault::latestFundingPaymentPointer() [staticcall] │ └─ ← 0 ├─ [0] VM::warp(1662951416 [1.662e9]) │ └─ ← () ├─ [48649] PerpetualAtlanticVault::updateFunding() │ ├─ [3315] MockToken::transfer(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], 4999999999999999999 [4.999e18]) │ │ ├─ emit Transfer(from: PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], to: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], amount: 4999999999999999999 [4.999e18]) │ │ └─ ← true │ ├─ [2031] PerpetualAtlanticVaultLP::addProceeds(4999999999999999999 [4.999e18]) │ │ ├─ [583] MockToken::balanceOf(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c]) [staticcall] │ │ │ └─ ← 54999999999999999999 [5.499e19] │ │ └─ ← () │ ├─ emit FundingPaid(sender: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], amount: 4999999999999999999 [4.999e18], latestFundingPaymentPointer: 0) │ ├─ emit FundingPaymentPointerUpdated(latestFundingPaymentPointer: 1) │ ├─ [3315] MockToken::transfer(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], 0) │ │ ├─ emit Transfer(from: PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], to: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], amount: 0) │ │ └─ ← true │ ├─ [2031] PerpetualAtlanticVaultLP::addProceeds(0) │ │ ├─ [583] MockToken::balanceOf(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c]) [staticcall] │ │ │ └─ ← 54999999999999999999 [5.499e19] │ │ └─ ← () │ ├─ emit FundingPaid(sender: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], amount: 0, latestFundingPaymentPointer: 1) │ └─ ← () ├─ [583] PerpetualAtlanticVaultLP::totalAvailableCollateral() [staticcall] │ └─ ← 39999999999999999999 [3.999e19] ├─ [583] PerpetualAtlanticVaultLP::totalAvailableCollateral() [staticcall] │ └─ ← 39999999999999999999 [3.999e19] ├─ [360] PerpetualAtlanticVaultLP::totalCollateral() [staticcall] │ └─ ← 54999999999999999999 [5.499e19] ├─ [360] PerpetualAtlanticVaultLP::totalCollateral() [staticcall] │ └─ ← 54999999999999999999 [5.499e19] ├─ [741] PerpetualAtlanticVault::updateFundingPaymentPointer() │ └─ ← () ├─ [385] PerpetualAtlanticVault::latestFundingPaymentPointer() [staticcall] │ └─ ← 1 ├─ [101124] PerpetualAtlanticVault::calculateFunding([15000000 [1.5e7]]) │ ├─ [324] MockRdpxEthPriceOracle::getRdpxPriceInEth() [staticcall] │ │ └─ ← 20000000 [2e7] │ ├─ [240] MockVolatilityOracle::getVolatility(15000000 [1.5e7]) [staticcall] │ │ └─ ← 100 │ ├─ [309] MockOptionPricing::getOptionPrice(15000000 [1.5e7], 20000000 [2e7], 100, 86400 [8.64e4]) [staticcall] │ │ └─ ← 5000000 [5e6] │ ├─ emit CalculateFunding(sender: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], amount: 100000000000000000000 [1e20], strike: 15000000 [1.5e7], fundingAmount: 5000000000000000000 [5e18], latestFundingPaymentPointer: 1) │ └─ ← 5000000000000000000 [5e18] ├─ [0] VM::startPrank(Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496]) │ └─ ← () ├─ [0] VM::expectRevert(PerpetualAtlanticVaultError(7)) │ └─ ← () ├─ [17113] PerpetualAtlanticVault::settle([0]) │ ├─ [3315] MockToken::transfer(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], 0) │ │ ├─ emit Transfer(from: PerpetualAtlanticVault: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], to: PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], amount: 0) │ │ └─ ← true │ ├─ [2031] PerpetualAtlanticVaultLP::addProceeds(0) │ │ ├─ [583] MockToken::balanceOf(PerpetualAtlanticVaultLP: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c]) [staticcall] │ │ │ └─ ← 54999999999999999999 [5.499e19] │ │ └─ ← () │ ├─ emit FundingPaid(sender: Integration: [0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496], amount: 0, latestFundingPaymentPointer: 1) │ ├─ [324] MockRdpxEthPriceOracle::getRdpxPriceInEth() [staticcall] │ │ └─ ← 20000000 [2e7] │ └─ ← "PerpetualAtlanticVaultError(7)" ├─ [0] VM::expectRevert(Arithmetic over/underflow) │ └─ ← () └─ ← "Arithmetic over/underflow"
Test result: ok. 1 passed; 0 failed; finished in 807.33ms