Search code examples
pythonsoliditysmartcontractstransferbrownie

Can't withdraw from smart contract


I'm trying to withdraw from this contract after funding it. After funding it, i checked the balance on goerli etherscan and there was goerliETH in it that i sent but i noticed that once i called withdraw the balance becomes 0 without sending it to my wallet address as intended.

The withdraw transcation was recorded but without any value, but under internal transactions i found out that the balance was transferred to the goerli black hole address.

I can't seem to find a way around this, any help will be greatly appreciated. This is the script below:

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

contract TimeControlled {
    address public owner;
    address[] private ownerArr;
    uint256 dateForWithdrawal;
    address public contractAddress;

    mapping(address => bool) private addressToBool;

    constructor(bool isAllowed) public {
        owner == msg.sender;
        contractAddress == address(this);
        addressToBool[msg.sender] = isAllowed;
        addressToBool[address(this)] = isAllowed;
        ownerArr.push(owner);
        ownerArr.push(contractAddress);
    }

    // fund the contract and return a true value
    function fund() public payable returns (bool) {
        return true;
    }

    // Check if the contract is being called by the owners
    // Require the owner to be the creators address or the contracts address
    modifier owners() {
        require(addressToBool[msg.sender], "You are not allowed!");
        _;
    }

    // withdraw at a certain time
    function withdraw() public payable owners returns (bool) {
        require(address(this).balance > 0);
        payable(owner).transfer(address(this).balance);
        return true; /// @notice for withdrawing from the contract
        /// @dev Withdraw by using the owners modifier and returns a boolean value
    }
}

Note: I deployed this contract from the constructor of another contract that i inherited it into. This is the contract below in case it is needed:

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@chainlink/contracts/src/v0.8/ChainlinkClient.sol";
import "./Timecontrolled.sol";

contract CallWithdraw is ChainlinkClient, TimeControlled {
    using Chainlink for Chainlink.Request;
    address public linkToken;
    uint256 public oraclePayment;
    address public oracle;
    bytes32 public jobId;
    uint256 public fundingPeriod = 5;

    constructor(
        address _linkToken,
        uint256 _oraclepayment,
        address _oracle,
        bytes32 _jobId
    ) public TimeControlled(true) {
        owner == msg.sender;
        oraclePayment = _oraclepayment;
        linkToken = _linkToken;
        oracle = _oracle;
        jobId = _jobId;
    }

    function callWithdraw() external {
        // if owner does not call the withdraw function at the set time
        // the contract calls withdraw on its own
        require(address(this).balance > 0);
        Chainlink.Request memory req = buildChainlinkRequest(
            jobId,
            address(this),
            this.fulfill.selector
        );
        req.addUint("until", block.timestamp + fundingPeriod * 1 minutes);
        withdraw();
        sendChainlinkRequestTo(oracle, req, oraclePayment);
    }

    function fulfill(bytes32 _requestId)
        public
        recordChainlinkFulfillment(_requestId)
    {
        address(this).balance == 0;
    }
}

Also this is my deploy script

from brownie import CallWithdraw, config
from scripts.helpful_scripts import get_account, network, get_contract
from web3 import Web3


oracle_payment = config["networks"][network.show_active()]["payment"]
oracle = config["networks"][network.show_active()]["oracle"]
job_Id = config["networks"][network.show_active()]["jobId"]


def deploy_call_withdraw_and_time_controlled():
    print(f"The network is {network.show_active()}")
    account = get_account()
    link_token = get_contract("link_token")
    print("Deploying contract...")
    call_withdraw = CallWithdraw.deploy(
        link_token.address,
        oracle_payment,
        oracle,
        job_Id,
        {"from": account},
    )
    """
    print("Transferring linktoken...")
        link_token.transfer(
        call_withdraw.address, Web3.toWei(1, "ether"), {"from": account}
    )
    print("Linktoken transferred successfully!")
    """

    print(account.balance())
    return call_withdraw


def fund():

    call_withdraw = CallWithdraw[-1]
    account = get_account()
    call_withdraw.fund({"value": Web3.toWei(0.03, "ether"), "from": account})
    print(f"{account.balance()} is the current balance")
    call_withdraw.withdraw({"from": account})
    print(f"{account.balance()} is the current balance")


def get_contract_balance():
    call_withdraw = CallWithdraw[-1]
    print(f"{call_withdraw.balance()} is {call_withdraw.address} balance")


def main():
    deploy_call_withdraw_and_time_controlled()
    fund()
    get_contract_balance()

Solution

  • Got help at ethereum.stackexchange.com and found out that it was an operator error. I changed owner == msg.sender to owner = msg.sender in my constructor and it worked fine.