contract UserWallet is UserAuth, UserNote {

    event LogExecute(address target, uint srcNum, uint sessionNum);

    /**
     * @dev sets the "address registry", owner's last activity, owner's active period and initial owner
     */
    constructor() public {
        registry = msg.sender;
        owner = msg.sender;
    }

    function() external payable {}

    /**
     * @dev Execute authorised calls via delegate call
     * @param _target logic proxy address
     * @param _data delegate call data
     * @param _src to find the source
     * @param _session to find the session
     */
    function execute(
        address _target,
        bytes memory _data,
        uint _src,
        uint _session
    ) 
        public
        payable
        note
        auth
        logicAuth(_target)
        returns (bytes memory response)
    {
        emit LogExecute(
            _target,
            _src,
            _session
        );
        
        // call contract in current context
        assembly {
            let succeeded := delegatecall(sub(gas, 5000), _target, add(_data, 0x20), mload(_data), 0, 0)
            let size := returndatasize

            response := mload(0x40)
            mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f))))
            mstore(response, size)
            returndatacopy(add(response, 0x20), 0, size)

            switch iszero(succeeded)
                case 1 {
                    // throw if delegatecall failed
                    revert(add(response, 0x20), size)
                }
        }
    }

}
/**
 * @title User Owned Contract Wallet
 */
function execute(
    address _target,
    bytes memory _data,
    uint _src,
    uint _session
) 
    public
    payable
    note
    auth
    logicAuth(_target)
    returns (bytes memory response)
{
    emit LogExecute(
        _target,
        _src,
        _session
    );
        
    // call contract in current context
    assembly {
        let succeeded := delegatecall(sub(gas, 5000), _target, add(_data, 0x20), mload(_data), 0, 0)
        let size := returndatasize

        response := mload(0x40)
        mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f))))
        mstore(response, size)
        returndatacopy(add(response, 0x20), 0, size)

        switch iszero(succeeded)
            case 1 {
                // throw if delegatecall failed
                revert(add(response, 0x20), size)
            }
    }
}

/**
 * @dev Execute authorised calls via delegate call
 * @param _target logic proxy address
 * @param _data delegate call data
 * @param _src to find the source
 * @param _session to find the session
 */