library RunTime {
    struct OutgoingAllowanceTrigger {
        address signer;
        uint marketId;
        uint amount;
    }

    struct TokenTransfer {
        address from;
        address to;
        address token;
        uint amount;
        bool isUsingDepositContract;
    }

    struct Context {
        address self;
        IDepositContractRegistry depositContractRegistry;
        address dydxExpiryContractAddress;
        Order.Info[] orders;
        address[] marketTokenAddress;
        ////////
        bytes32[] depositFlagTriggers;
        TokenTransfer[] tokenTransfers;
        OutgoingAllowanceTrigger[] setOutgoingAllowanceTriggers;
        DydxPosition.Info[] dydxPositions;
        DydxActions.ActionArgs[] dydxBeforeActions;
        DydxActions.ActionArgs[] dydxAfterActions;
        uint numDepositFlagTriggers;
        uint numTokenTransfers;
        uint numSetOutgoingAllowanceTriggers;
        uint numDydxPositions;
        uint numDydxBeforeActions;
        uint numDydxAfterActions;
    }

    // ---------------------------------

    function setDepositFlag(Context memory ctx, bytes32 orderHash) internal pure {
        ctx.depositFlagTriggers[ctx.numDepositFlagTriggers] = orderHash;
        ctx.numDepositFlagTriggers += 1;
    }

    function requireTokenTransfer(
        Context memory ctx,
        address from,
        address to,
        address token,
        uint amount,
        bool isUsingDepositContract
    ) internal pure {
        for (uint i = 0; i < ctx.numTokenTransfers; i++) {
            TokenTransfer memory transfer = ctx.tokenTransfers[i];
            if (transfer.from == from && transfer.to == to && transfer.token == token) {
                transfer.amount += amount;
                return;
            }
        }

        ctx.tokenTransfers[ctx.numTokenTransfers] = TokenTransfer(from, to, token, amount, isUsingDepositContract);
        ctx.numTokenTransfers += 1;
    }

    function registerPosition(
        Context memory ctx,
        address trader,
        uint positionId
    ) internal pure returns (uint) {
        for (uint i = 0; i < ctx.numDydxPositions; i++) {
            if (ctx.dydxPositions[i].owner == trader && ctx.dydxPositions[i].number == positionId) {
                return i;
            }
        }

        ctx.dydxPositions[ctx.numDydxPositions] = DydxPosition.Info(trader, positionId);
        ctx.numDydxPositions += 1;
        return ctx.numDydxPositions - 1;
    }

    function addBeforeAction(Context memory ctx, DydxActions.ActionArgs memory action) internal pure {
        ctx.dydxBeforeActions[ctx.numDydxBeforeActions] = action;
        ctx.numDydxBeforeActions += 1;
    }

    function addAfterAction(Context memory ctx, DydxActions.ActionArgs memory action) internal pure {
        ctx.dydxAfterActions[ctx.numDydxAfterActions] = action;
        ctx.numDydxAfterActions += 1;
    }
}
function setDepositFlag(Context memory ctx, bytes32 orderHash) internal pure {
    ctx.depositFlagTriggers[ctx.numDepositFlagTriggers] = orderHash;
    ctx.numDepositFlagTriggers += 1;
}

// ---------------------------------