0

I'm creating a smart contract where exploiter send exploited funds to exploited protocol and automatically get a portion back as the bounty. Here's the smart contract:

// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma solidity >=0.8.0 <0.9.0;

contract GreyHat {
    constructor() {}

    // protocols => exploiter
    // mapping(address => address) public protocols;
    mapping (address => bool) public implemented;
    uint256 bountyPortion = 20;


    function implement() public {
        require(implemented[msg.sender] == false, "Already implemented");
        implemented[msg.sender] = true;
    }

    function depositExploitedFund(address protocol) payable public {
        require(implemented[protocol] == true, "Protocol hasn't implement contract");
        (bool s, ) = payable(protocol).call{value: msg.value}("");
        require(s, "Deposit fund failed");
        _rewardBounty(msg.value); 
    }

    function _rewardBounty(uint256 fund) private {
        uint256 bounty = fund * bountyPortion / 100;
        (bool s, ) = tx.origin.call{value: bounty}("");    
        require(s, "Reward bounty failed");
    }
}

I get this error on Remix

transact to GreyHat.depositExploitedFund errored: Error occurred: revert.

revert
    The transaction has been reverted to the initial state.
Reason provided by the contract: "Reward bounty failed".
You may want to cautiously increase the gas limit if the transaction went out of gas.
1
  • Please mark the answer as correct. Commented May 5 at 16:33

1 Answer 1

0

You are sending all the msg.value to the exploited protocol. No surprise that the SC has no more funds to reward the exploiter. You should send to the protocol 100 - bountyPortion.

pragma solidity >=0.8.0 <0.9.0;

contract GreyHat {
    constructor() {}

    // protocols => exploiter
    // mapping(address => address) public protocols;
    mapping (address => bool) public implemented;
    uint256 bountyPortion = 20;


    function implement() public {
        require(implemented[msg.sender] == false, "Already implemented");
        implemented[msg.sender] = true;
    }

    function depositExploitedFund(address protocol) payable public {
        require(implemented[protocol] == true, "Protocol hasn't implement contract");
        _returnExploited(protocol, msg.value);
        _rewardBounty(msg.value);
    }

    function _returnExploited(address protocol, uint256 fund) private {
        uint256 exploited = fund * (100 - bountyPortion) / 100;
        (bool s, ) = protocol.call{value: exploited}("");    
        require(s, "Return exploited failed");
    }

    function _rewardBounty(uint256 fund) private {
        uint256 bounty = fund * bountyPortion / 100;
        (bool s, ) = tx.origin.call{value: bounty}("");    
        require(s, "Reward bounty failed");
    }
}
2
  • woule be problem if I use msg.sender instead of tx.origin in _rewardBounty? I test using msg.sender and it still works normally ``` function _rewardBounty(uint256 fund) private { (bool s, ) = msg.sender.call{value: fund}(""); require(s, "Reward bounty failed"); } ```
    – dtnwen
    Commented May 6 at 8:15
  • Depends on your implementation. msg.sender changes throughout the execution of a transaction. If you were to implement a further layer (new smart contract) that calls depositExplotedFund(), then the contract calling the function would be the msg.sender. On the other hand, tx.origin is not dynamic and is always the EOA account making the tx. Commented May 6 at 11:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.