отозвать или аннулировать токен по истечении 30 минут

Цель децентрализованного приложения/смарт-контракта

Я отправляю x количество эфира на адрес "AAA" с адреса "000"

Если через 10 минут, если вновь полученный адрес «AAA» все еще имеет все x количество эфира. Он должен вернуть весь эфир обратно на адрес «000», регистр «неиспользованный» для этой транзакции.

Может ли кто-нибудь показать этот PoC с помощью Solidity-Browser?

Спасибо

Ответы (1)

Если Алиса заплатит Бобу, мы не сможем заставить Боба вернуть деньги.

Алиса может заплатить по контракту и указать, что Боб является единственным лицом, уполномоченным тратить эти средства. Мы можем дополнительно указать крайний срок, после которого Боб больше не имеет права тратить средства, а Алиса имеет право требовать возмещения.

Еще одна сложность заключается в том, что у Боба может быть много таких депозитов, каждый со своими крайними сроками, и поэтому становится довольно неудобно иметь дело с ним как с единовременной суммой чистого остатка. Вместо этого в приведенном ниже примере каждый транш отслеживается как конкретный депозит со своим крайним сроком, и каждый раз, когда Боб пересылает средства, он указывает, какой транш (с именем DepositNumber) он тратит.

Он использует ленивый процесс вывода средств, чтобы вернуть средства Алисе, если они не перенаправлены кому-то еще до истечения срока. Алиса заинтересована в получении возмещения, поэтому она проверит контракт и заплатит за газ, чтобы обработать его.

Ниже просто наспех задуманная мазня без проверки. Это приближает идею. Надеюсь, поможет.

    pragma solidity ^0.4.6;

// Alice gives Bob ETH to spend before deadline, or Alice gets it back. 
// Alice = sender
// Bob = spender
// recipient is whomever Bob decides to forward to

contract ForcedForward {

    struct DepositStruct {
        address sender;
        uint amount;
        uint blockNumber;
        uint deadline;
    }

    mapping(address => DepositStruct[]) spenderDepositStructs;

    event LogReceived (address spender, uint depositNumber, uint amount, uint deadline, address sender);
    event LogForwarded(address spender, uint depositNumber, uint amount, address recipient);
    event LogWithdrawn(address spender, uint depositNumber, uint amount, address sender);

    //////////////////////////////////
    // Send funds and authorize
    // someone else to spend before
    // a certain deadline (block)

    function deposit(address spender, uint deadline)
        public
        payable
        returns(bool success)
    {
        if(deadline <= block.number) throw; // must be in the future
        if(msg.value==0) throw; // no money sent
        DepositStruct memory d;
        d.sender = msg.sender;
        d.amount = msg.value;
        d.deadline = deadline;
        spenderDepositStructs[spender].push(d);
        LogReceived(spender, spenderDepositStructs[spender].length-1, msg.value, deadline, msg.sender);
        return true;
    }

    //////////////////////////////////
    // Forward funds if authorized to
    // before the deadline is passed

    function forward(address recipient, uint depositNumber)
        public
        returns(bool success)
    {
        DepositStruct d = spenderDepositStructs[msg.sender][depositNumber];
        if(d.deadline < block.number) throw; // too late
        uint amount = d.amount;
        if(amount == 0) throw; // no money
        spenderDepositStructs[msg.sender][depositNumber].amount = 0; // zero out the balance
        if(!recipient.send(d.amount)) throw;
        LogForwarded(msg.sender, depositNumber, amount, recipient);
        return true;
    }

    //////////////////////////////////
    // Clawback funds 

    function withdraw(address spender, uint depositNumber)
        public
        returns(bool success)
    {
        DepositStruct d = spenderDepositStructs[spender][depositNumber];
        if(d.sender != msg.sender) throw; // not originator. not entitled to it. Error. 
        if(d.deadline > block.number) throw; // too soon
        uint amount = d.amount;
        spenderDepositStructs[spender][depositNumber].amount = 0; // zero out the balance. 
        if(amount==0) throw; // no money
        if(!msg.sender.send(amount)) throw; // try to send it back
        LogWithdrawn(spender, depositNumber, amount, msg.sender);
        return true;
    }

    ///////////////////////////////////////////
    // Getter functions for visibility

    function getSpenderDepositCount(address spender) 
        public
        constant
        returns(uint spenderDepositCount)
    {
        return spenderDepositStructs[spender].length;
    }

    function getSpenderDeposit(address spender, uint depositNumber)
        public
        constant
        returns(address sender, uint amount, uint deadline)
    {
        DepositStruct d;
        d = spenderDepositStructs[spender][depositNumber];
        return(d.sender, d.amount, d.deadline);
    }

}