2

Attempting to test this repo in Ubuntu 18.04: https://github.com/ETH-Pantheon/Aion

Truffle v4.1.14 (core: 4.1.14)
Solidity v0.4.24 (solc-js)

Here is the main contract I've already deployed to my testnet:

pragma solidity ^0.4.24; 

/* ----------------------------------------------------------------------------
 Client contract.
 This contract is generated for each user (user account). All the transactions of a user are executed from this contract.
 Only Aion smart contract can interact with the user account and only when the user schedules transactions.
 ----------------------------------------------------------------------------*/

contract AionClient {

    address private AionAddress;

    constructor(address addraion) public{
        AionAddress = addraion;
    }


    function execfunct(address to, uint256 value, uint256 gaslimit, bytes data) external returns(bool) {
        require(msg.sender == AionAddress);
        return to.call.value(value).gas(gaslimit)(data);

    }


    function () payable public {}

}


// ----------------------------------------------------------------------------
// SafeMat library
// ----------------------------------------------------------------------------
library SafeMath {
  /** @dev Multiplies two numbers, throws on overflow.*/
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) {return 0;}
        uint256 c = a * b;
        require(c / a == b);
        return c;
    }

  /** @dev Integer division of two numbers, truncating the quotient.*/
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a / b;
        return c;
    }

  /**@dev Substracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).*/
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a);
        return a - b;
    }

  /** @dev Adds two numbers, throws on overflow.*/
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a);
        return c;
    }

}



/* ----------------------------------------------------------------------------
 Aion Smart contract (by ETH-Pantheon)
  ----------------------------------------------------------------------------*/

contract Aion {
    using SafeMath for uint256;

    address public owner;
    uint256 public serviceFee;
    uint256 public AionID;
    uint256 public feeChangeInterval;
    mapping(address => address) public clientAccount;
    mapping(uint256 => bytes32) public scheduledCalls;

    // Log for executed transactions.
    event ExecutedCallEvent(address indexed from, uint256 indexed AionID, bool TxStatus, bool TxStatus_cancel, bool reimbStatus);

    // Log for scheduled transactions.                        
    event ScheduleCallEvent(uint256 indexed blocknumber, address indexed from, address to, uint256 value, uint256 gaslimit,
                            uint256 gasprice, uint256 fee, bytes data, uint256 indexed AionID, bool schedType);

    // Log for cancelation of a scheduled call (no fee is charged, all funds are moved from client's smart contract to client's address)                        
    event CancellScheduledTxEvent(address indexed from, uint256 Total, bool Status, uint256 indexed AionID);


    // Log for changes in the service fee
    event feeChanged(uint256 newfee, uint256 oldfee);




    constructor () public {
        owner = msg.sender;
        serviceFee = 500000000000000;
    }    

    // This function allows to change the address of the owner (admin of the contract)
    function transferOwnership(address newOwner) public {
        require(msg.sender == owner);
        withdraw();
        owner = newOwner;
    }

    // This function creates an account (contract) for a client if his address is 
    // not yet associated to an account
    function createAccount() internal {
        if(clientAccount[msg.sender]==address(0x0)){
            AionClient newContract = new AionClient(address(this));
            clientAccount[msg.sender] = address(newContract);
        }
    }



    /* This function schedules transactions: client should provide an amount of Ether equal to value + gaslimit*gasprice + serviceFee
    @param blocknumber block or timestamp at which the transaction should be executed. 
    @param to recipient of the transaction.
    @param value Amount of Wei to send with the transaction.
    @param gaslimit maximum amount of gas to spend in the transaction.
    @param gasprice value to pay per unit of gas.
    @param data transaction data.
    @param schedType determines if the transaction is scheduled on blocks or timestamp (true->timestamp)
    @return uint256 Identification of the transaction
    @return address address of the client account created
    */
    function ScheduleCall(uint256 blocknumber, address to, uint256 value, uint256 gaslimit, uint256 gasprice, bytes data, bool schedType) public payable returns (uint,address){
        require(msg.value == value.add(gaslimit.mul(gasprice)).add(serviceFee));
        AionID = AionID + 1;
        scheduledCalls[AionID] = keccak256(abi.encodePacked(blocknumber, msg.sender, to, value, gaslimit, gasprice, serviceFee, data, schedType));
        createAccount();
        clientAccount[msg.sender].transfer(msg.value);
        emit ScheduleCallEvent(blocknumber, msg.sender, to, value, gaslimit, gasprice, serviceFee, data, AionID, schedType);
        return (AionID,clientAccount[msg.sender]);
    }


    /* This function executes the transaction at the correct time/block
    Aion off-chain system should provide the correct information for executing a transaction.
    The information is checked against the hash of the original data provided by the user saved in scheduledCalls.
    If the information does not match, the transaction is reverted.
    */
    function executeCall(uint256 blocknumber, address from, address to, uint256 value, uint256 gaslimit, uint256 gasprice,
                         uint256 fee, bytes data, uint256 aionId, bool schedType) external {
        require(msg.sender==owner);
        if(schedType) require(blocknumber <= block.timestamp);
        if(!schedType) require(blocknumber <= block.number);

        require(scheduledCalls[aionId]==keccak256(abi.encodePacked(blocknumber, from, to, value, gaslimit, gasprice, fee, data, schedType)));
        AionClient instance = AionClient(clientAccount[from]);

        require(instance.execfunct(address(this), gasprice*gaslimit+fee, 2100, hex"00"));
        bool TxStatus = instance.execfunct(to, value, gasleft().sub(50000), data);

        // If the user tx fails return the ether to user
        bool TxStatus_cancel;
        if(!TxStatus && value>0){TxStatus_cancel = instance.execfunct(from, value, 2100, hex"00");}

        delete scheduledCalls[aionId];
        bool reimbStatus = from.call.value((gasleft()).mul(gasprice)).gas(2100)();
        emit ExecutedCallEvent(from, aionId,TxStatus, TxStatus_cancel, reimbStatus);

    }


    /* This function allows clients to cancel scheduled transctions. No fee is charged.
    Parameters are the same as in ScheduleCall.
    @return bool indicating success or failure.
    */
    function cancellScheduledTx(uint256 blocknumber, address from, address to, uint256 value, uint256 gaslimit, uint256 gasprice,
                         uint256 fee, bytes data, uint256 aionId, bool schedType) external returns(bool) {
        if(schedType) require(blocknumber >=  block.timestamp+(3 minutes) || blocknumber <= block.timestamp-(5 minutes));
        if(!schedType) require(blocknumber >  block.number+10 || blocknumber <= block.number-20);
        require(scheduledCalls[aionId]==keccak256(abi.encodePacked(blocknumber, from, to, value, gaslimit, gasprice, fee, data, schedType)));
        require(msg.sender==from);
        AionClient instance = AionClient(clientAccount[msg.sender]);

        bool Status = instance.execfunct(from, value+gasprice*gaslimit+fee, 3000, hex"00");
        require(Status);
        emit CancellScheduledTxEvent(from, value+gasprice*gaslimit+fee, Status, aionId);
        delete scheduledCalls[aionId];
        return true;
    }




    // This function allows the owner of the contract to retrieve the fees and the gas price
    function withdraw() public {
        require(msg.sender==owner);
        owner.transfer(address(this).balance);
    }


    // This function updates the service fee.
    // To provide security to the clients the fee can only be updated once per day.
    // This is to maintain the same price despite the Ether variation.
    // Also, the amount of the update (if increased) can only increase 10% each time.
    // Furthermore, an event is fired when the fee has been changed to inform the network.
    function updatefee(uint256 fee) public{
        require(msg.sender==owner);
        require(feeChangeInterval<block.timestamp);
        uint256 oldfee = serviceFee;
        if(fee>serviceFee){
            require(((fee.sub(serviceFee)).mul(100)).div(serviceFee)<=10);
            serviceFee = fee;
        } else{
            serviceFee = fee;
        }
        feeChangeInterval = block.timestamp + (1 days);
        emit feeChanged(serviceFee, oldfee);
    } 



    // fallback- receive Ether
    function () public payable {

    }



}

Here's my example contract, Sched.sol:

pragma solidity ^0.4.24;

// interface Aion
contract Aion {
uint256 public serviceFee;
function ScheduleCall(uint256 blocknumber, address to, uint256 value, uint256 gaslimit, uint256 gasprice, bytes data, bool schedType) public payable returns (uint);
function cancellScheduledTx(uint256 blocknumber, address from, address to, uint256 value, uint256 gaslimit, uint256 gasprice,
                     uint256 fee, bytes data, uint256 aionId, bool schedType) external returns(bool);

}

// Main contract
contract MyContract{
Aion aion;
address aionAccount;

function scheduleTransaction(uint256 value, uint256 gaslimit, uint256 gasprice, bool time_or_block) public {
    aion = Aion(0xD916EdFd054E1c0fE8e0979DF3818bd60313Bc62); //contract address of deployed Aion contract to interact with
    uint256 callCost = value + gaslimit*gasprice + aion.serviceFee();
    uint256 txId;
    (txId,aionAccount) = aion.ScheduleCall.value(callCost)(block.number+15, address(this), value, gaslimit, gasprice,hex"00",time_or_block);
}

function () public payable {}

}

When I run truffle compile, I get the following error:

/home/melvin/schedule/contracts/Sched.sol:21:23: TypeError: Type uint256 is not implicitly convertible to expected type tuple(uint256,address).
(txId,aionAccount) = aion.ScheduleCall.value(callCost)(block.number+15, address(this), value, gaslimit, gasprice,hex"00",time_or_block);    
                     ^----------------------------------------------------------------------------------------------------------------^

Any ideas? I'm not great with Solidity yet, if you think it's something simple, it probably is, let me know! Thanks.

1

Here, in this declaration add address in along with uint in the returns

function ScheduleCall(uint256 blocknumber, address to, uint256 value, uint256 gaslimit, uint256 gasprice, bytes data, bool schedType) public payable returns (uint,address);

Then it would work.

  • That worked, and makes sense, equal input and output. Thanks! – Erik Schneider Oct 1 '18 at 2:57
0

I believe ScheduleCallreturns uint and you are trying to assign that type to a tuple(uint, address).

So you might want to do something like this:

(txId,aionAccount) = (aion.ScheduleCall.value(callCost)(block.number+15, address(this), value, gaslimit, gasprice,hex"00",time_or_block), theAionAccountHere);

Not sure this would work but seems logical to me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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