Skip to content

Comments

feat: Add BalanceDropTrap example with working config and tests#32

Open
hyapiskan wants to merge 2 commits intodrosera-network:mainfrom
hyapiskan:my-balance-trap
Open

feat: Add BalanceDropTrap example with working config and tests#32
hyapiskan wants to merge 2 commits intodrosera-network:mainfrom
hyapiskan:my-balance-trap

Conversation

@hyapiskan
Copy link

No description provided.

@hyapiskan
Copy link
Author

Hello Drosera Team,

Thanks for the review! Here are the contents of the files for the Proof-of-Concept trap as requested:


foundry/balance-drop-trap/src/BalanceDropTrap.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {ITrap} from "drosera-contracts/interfaces/ITrap.sol";

// This trap detects sudden drops in the ETH balance of a specific wallet.
contract BalanceDropTrap is ITrap {
    // The wallet address to monitor (Example: Vitalik Buterin's address)
    address constant TARGET_WALLET = 0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B;
    // The threshold percentage for the alert (e.g., if it drops by more than 50%)
    uint256 constant THRESHOLD_PERCENT = 50;

    // This function runs on every block and records the wallet's current ETH balance.
    function collect() external view returns (bytes memory) {
        return abi.encode(TARGET_WALLET.balance);
    }

    // This function analyzes the data from past blocks.
    function shouldRespond(bytes[] calldata data) external pure returns (bool, bytes memory) {
        // At least 2 blocks of data are needed for analysis (previous and current balance).
        if (data.length < 2) {
            return (false, bytes(""));
        }

        uint256 previousBalance = abi.decode(data[data.length - 2], (uint256));
        uint256 currentBalance = abi.decode(data[data.length - 1], (uint256));

        // If the balance has not dropped or the previous balance was 0, there is no issue.
        if (currentBalance >= previousBalance || previousBalance == 0) {
            return (false, bytes(""));
        }

        // Calculate the drop amount and percentage.
        uint256 dropAmount = previousBalance - currentBalance;
        uint256 dropPercentage = (dropAmount * 100) / previousBalance;

        // If the drop percentage is greater than our threshold, TRIGGER THE ALARM!
        if (dropPercentage >= THRESHOLD_PERCENT) {
            return (true, abi.encode(previousBalance, currentBalance));
        }

        // If the drop is less than the threshold, there is no issue.
        return (false, bytes(""));
    }
}

foundry/balance-drop-trap/test/BalanceDropTrap.t.sol


// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {Test} from "forge-std/Test.sol";
import {BalanceDropTrap} from "../../src/BalanceDropTrap.sol";

// Our test contract inherits from Foundry's Test contract.
contract BalanceDropTrapTest is Test {
    BalanceDropTrap public trap;

    // This function runs before each test and deploys our trap.
    function setUp() public {
        trap = new BalanceDropTrap();
    }

    // This test verifies that the trap should respond on a significant drop.
    function testShouldRespondOnSignificantDrop() public {
        // We simulate historical data.
        bytes[] memory data = new bytes[](2);
        
        // Previous balance: 100 ETH
        data = abi.encode(100 ether);
        // Current balance: 40 ETH (a 60% drop)
        data = abi.encode(40 ether);

        // We call our trap's shouldRespond function with this mock data.
        (bool should, ) = trap.shouldRespond(data);

        // We expect the result to be 'true' and assert this.
        assertTrue(should, "Trap should respond on a >50% balance drop");
    }

    // This test verifies that the trap should NOT respond on an insignificant drop.
    function testShouldNotRespondOnInsignificantDrop() public {
        // We simulate historical data.
        bytes[] memory data = new bytes[](2);
        
        // Previous balance: 100 ETH
        data = abi.encode(100 ether);
        // Current balance: 80 ETH (a 20% drop)
        data = abi.encode(80 ether);

        (bool should, ) = trap.shouldRespond(data);

        // We expect the result to be 'false' and assert this.
        assertFalse(should, "Trap should NOT respond on a <50% balance drop");
    }
}



foundry/balance-drop-trap/foundry.toml



[profile.default]
src = 'src'
test = 'test'
libs = ['../../node_modules']
remappings = [
    'drosera-contracts/=../../node_modules/contracts/src/',
    'forge-std/=../../node_modules/forge-std/src/'
]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant