contract DSSpell is DSExec, DSNote {
    address public whom;
    uint256 public mana;
    bytes   public data;
    bool    public done;

    constructor(address whom_, uint256 mana_, bytes memory data_) public {
        whom = whom_;
        mana = mana_;
        data = data_;
    }
    // Only marked 'done' if CALL succeeds (not exceptional condition).
    function cast() public note {
        require(!done, "ds-spell-already-cast");
        exec(whom, data, mana);
        done = true;
    }
}
function cast() public note {
    require(!done, "ds-spell-already-cast");
    exec(whom, data, mana);
    done = true;
}

// Only marked 'done' if CALL succeeds (not exceptional condition).