Blockwell

TradeModule

About

Stats

Public Functions 3
Event Types 1
Code Size 89,860 bytes

Library Use

Uses SafeCast for int256.
Uses SafeMath for uint256.
Uses Invoke for ISetToken.
Uses Position for ISetToken.
Uses PreciseUnitMath for uint256.

Events (1) keyboard_arrow_up

ComponentExchanged Event

Parameters help
_setToken
ISetToken help
_sendToken
address help
_receiveToken
address help
_exchangeAdapter
IExchangeAdapter help
_totalSendAmount
uint256 help
_totalReceiveAmount
uint256 help
_protocolFee
uint256 help

TradeInfo Struct

Members
setToken
ISetToken help
exchangeAdapter
IExchangeAdapter help
sendToken
address help
receiveToken
address help
setTotalSupply
uint256 help
totalSendQuantity
uint256 help
totalMinReceiveQuantity
uint256 help
preTradeSendTokenBalance
uint256 help
preTradeReceiveTokenBalance
uint256 help

TRADE_MODULE_PROTOCOL_FEE_INDEX Constant

uint256 help
0

_NOT_ENTERED Constant

uint256 help
1

_ENTERED Constant

uint256 help
2

controller Variable

address help

_status Variable

uint256 help
Internal Variable

Functions Expand All Collapse All

initialize keyboard_arrow_up

Parameters help

Name Type
_setToken
ISetToken help

Properties

Visibility help public
Mutability help transaction

Modifiers help

onlyValidAndPendingSet checks for the following:
null
onlySetManager checks for the following:
null
Source Code
function initialize(ISetToken _setToken)
  external
  onlyValidAndPendingSet(_setToken)
  onlySetManager(_setToken, msg.sender)
{
  _setToken.initializeModule();
}

trade keyboard_arrow_up

Parameters help

Name Type
_setToken
ISetToken help
_exchangeName
string help
_sendToken
address help
_sendQuantity
uint256 help
_receiveToken
address help
_minReceiveQuantity
uint256 help
_data
bytes help

Properties

Visibility help public
Mutability help transaction

Modifiers help

Requirements help

Source Code
function trade(
  ISetToken _setToken,
  string memory _exchangeName,
  address _sendToken,
  uint256 _sendQuantity,
  address _receiveToken,
  uint256 _minReceiveQuantity,
  bytes memory _data
) external nonReentrant onlyManagerAndValidSet(_setToken) {
  TradeInfo memory tradeInfo = _createTradeInfo(
    _setToken,
    _exchangeName,
    _sendToken,
    _receiveToken,
    _sendQuantity,
    _minReceiveQuantity
  );

  _validatePreTradeData(tradeInfo, _sendQuantity);

  _executeTrade(tradeInfo, _data);

  uint256 exchangedQuantity = _validatePostTrade(tradeInfo);

  uint256 protocolFee = _accrueProtocolFee(tradeInfo, exchangedQuantity);

  (uint256 netSendAmount, uint256 netReceiveAmount) = _updateSetTokenPositions(
    tradeInfo
  );

  emit ComponentExchanged(
    _setToken,
    _sendToken,
    _receiveToken,
    tradeInfo.exchangeAdapter,
    netSendAmount,
    netReceiveAmount,
    protocolFee
  );
}

removeModule keyboard_arrow_up

Parameters help

This function has no parameters.

Properties

Visibility help public
Mutability help transaction
Source Code
function removeModule() external override {}

Internal Functions Expand All Collapse All

Internal functions are parts of the contract that can't be used directly, but instead are used by the public functions listed above.

internal TradeModule._createTradeInfo keyboard_arrow_up

Parameters help

Name Type
_setToken
ISetToken help
_exchangeName
string help
_sendToken
address help
_receiveToken
address help
_sendQuantity
uint256 help
_minReceiveQuantity
uint256 help

Properties

Visibility help internal
Mutability help view
Source Code
function _createTradeInfo(
  ISetToken _setToken,
  string memory _exchangeName,
  address _sendToken,
  address _receiveToken,
  uint256 _sendQuantity,
  uint256 _minReceiveQuantity
) internal view returns (TradeInfo memory) {
  TradeInfo memory tradeInfo;

  tradeInfo.setToken = _setToken;

  tradeInfo.exchangeAdapter = IExchangeAdapter(
    getAndValidateAdapter(_exchangeName)
  );

  tradeInfo.sendToken = _sendToken;
  tradeInfo.receiveToken = _receiveToken;

  tradeInfo.setTotalSupply = _setToken.totalSupply();

  tradeInfo.totalSendQuantity = Position.getDefaultTotalNotional(
    tradeInfo.setTotalSupply,
    _sendQuantity
  );

  tradeInfo.totalMinReceiveQuantity = Position.getDefaultTotalNotional(
    tradeInfo.setTotalSupply,
    _minReceiveQuantity
  );

  tradeInfo.preTradeSendTokenBalance = IERC20(_sendToken).balanceOf(
    address(_setToken)
  );
  tradeInfo.preTradeReceiveTokenBalance = IERC20(_receiveToken).balanceOf(
    address(_setToken)
  );

  return tradeInfo;
}

internal TradeModule._validatePreTradeData keyboard_arrow_up

Parameters help

Name Type
_tradeInfo
TradeInfo help
_sendQuantity
uint256 help

Properties

Visibility help internal
Mutability help view

Requirements help

Source Code
function _validatePreTradeData(
  TradeInfo memory _tradeInfo,
  uint256 _sendQuantity
) internal view {
  require(_tradeInfo.totalSendQuantity > 0, "Token to sell must be nonzero");

  require(
    _tradeInfo.setToken.hasSufficientDefaultUnits(
      _tradeInfo.sendToken,
      _sendQuantity
    ),
    "Unit cant be greater than existing"
  );
}

internal TradeModule._executeTrade keyboard_arrow_up

Parameters help

Name Type
_tradeInfo
TradeInfo help
_data
bytes help

Properties

Visibility help internal
Mutability help transaction
Source Code
function _executeTrade(TradeInfo memory _tradeInfo, bytes memory _data)
  internal
{
  // Get spender address from exchange adapter and invoke approve for exact amount on SetToken
  _tradeInfo.setToken.invokeApprove(
    _tradeInfo.sendToken,
    _tradeInfo.exchangeAdapter.getSpender(),
    _tradeInfo.totalSendQuantity
  );

  (
    address targetExchange,
    uint256 callValue,
    bytes memory methodData
  ) = _tradeInfo.exchangeAdapter.getTradeCalldata(
    _tradeInfo.sendToken,
    _tradeInfo.receiveToken,
    address(_tradeInfo.setToken),
    _tradeInfo.totalSendQuantity,
    _tradeInfo.totalMinReceiveQuantity,
    _data
  );

  _tradeInfo.setToken.invoke(targetExchange, callValue, methodData);
}

internal TradeModule._validatePostTrade keyboard_arrow_up

Parameters help

Name Type
_tradeInfo
TradeInfo help

Properties

Visibility help internal
Mutability help view
Source Code
function _validatePostTrade(TradeInfo memory _tradeInfo)
  internal
  view
  returns (uint256)
{
  uint256 exchangedQuantity = IERC20(_tradeInfo.receiveToken)
  .balanceOf(address(_tradeInfo.setToken))
  .sub(_tradeInfo.preTradeReceiveTokenBalance);

  require(
    exchangedQuantity >= _tradeInfo.totalMinReceiveQuantity,
    "Slippage greater than allowed"
  );

  return exchangedQuantity;
}

internal TradeModule._accrueProtocolFee keyboard_arrow_up

Parameters help

Name Type
_tradeInfo
TradeInfo help
_exchangedQuantity
uint256 help

Properties

Visibility help internal
Mutability help transaction
Source Code
function _accrueProtocolFee(
  TradeInfo memory _tradeInfo,
  uint256 _exchangedQuantity
) internal returns (uint256) {
  uint256 protocolFeeTotal = getModuleFee(
    TRADE_MODULE_PROTOCOL_FEE_INDEX,
    _exchangedQuantity
  );

  payProtocolFeeFromSetToken(
    _tradeInfo.setToken,
    _tradeInfo.receiveToken,
    protocolFeeTotal
  );

  return protocolFeeTotal;
}

internal TradeModule._updateSetTokenPositions keyboard_arrow_up

Parameters help

Name Type
_tradeInfo
TradeInfo help

Properties

Visibility help internal
Mutability help transaction
Source Code
function _updateSetTokenPositions(TradeInfo memory _tradeInfo)
  internal
  returns (uint256, uint256)
{
  (uint256 currentSendTokenBalance, , ) = _tradeInfo
  .setToken
  .calculateAndEditDefaultPosition(
    _tradeInfo.sendToken,
    _tradeInfo.setTotalSupply,
    _tradeInfo.preTradeSendTokenBalance
  );

  (uint256 currentReceiveTokenBalance, , ) = _tradeInfo
  .setToken
  .calculateAndEditDefaultPosition(
    _tradeInfo.receiveToken,
    _tradeInfo.setTotalSupply,
    _tradeInfo.preTradeReceiveTokenBalance
  );

  return (
    _tradeInfo.preTradeSendTokenBalance.sub(currentSendTokenBalance),
    currentReceiveTokenBalance.sub(_tradeInfo.preTradeReceiveTokenBalance)
  );
}

internal ModuleBase.transferFrom keyboard_arrow_up

Parameters help

Name Type
_token
IERC20 help
_from
address help
_to
address help
_quantity
uint256 help

Properties

Visibility help internal
Mutability help transaction
Source Code
function transferFrom(
  IERC20 _token,
  address _from,
  address _to,
  uint256 _quantity
) internal {
  ExplicitERC20.transferFrom(_token, _from, _to, _quantity);
}

internal ModuleBase.getAndValidateAdapter keyboard_arrow_up

Parameters help

Name Type
_integrationName
string help

Properties

Visibility help internal
Mutability help view

Requirements help

Source Code
function getAndValidateAdapter(string memory _integrationName)
  internal
  view
  returns (address)
{
  bytes32 integrationHash = getNameHash(_integrationName);
  return getAndValidateAdapterWithHash(integrationHash);
}

internal ModuleBase.getAndValidateAdapterWithHash keyboard_arrow_up

Parameters help

Name Type
_integrationHash
bytes32 help

Properties

Visibility help internal
Mutability help view

Requirements help

Source Code
function getAndValidateAdapterWithHash(bytes32 _integrationHash)
  internal
  view
  returns (address)
{
  address adapter = controller
  .getIntegrationRegistry()
  .getIntegrationAdapterWithHash(address(this), _integrationHash);

  require(adapter != address(0), "Must be valid adapter");
  return adapter;
}

internal ModuleBase.getModuleFee keyboard_arrow_up

Parameters help

Name Type
_feeIndex
uint256 help
_quantity
uint256 help

Properties

Visibility help internal
Mutability help view
Source Code
function getModuleFee(uint256 _feeIndex, uint256 _quantity)
  internal
  view
  returns (uint256)
{
  uint256 feePercentage = controller.getModuleFee(address(this), _feeIndex);
  return _quantity.preciseMul(feePercentage);
}

internal ModuleBase.payProtocolFeeFromSetToken keyboard_arrow_up

Parameters help

Name Type
_setToken
ISetToken help
_token
address help
_feeQuantity
uint256 help

Properties

Visibility help internal
Mutability help transaction
Source Code
function payProtocolFeeFromSetToken(
  ISetToken _setToken,
  address _token,
  uint256 _feeQuantity
) internal {
  if (_feeQuantity > 0) {
    _setToken.strictInvokeTransfer(
      _token,
      controller.feeRecipient(),
      _feeQuantity
    );
  }
}

internal ModuleBase.isSetPendingInitialization keyboard_arrow_up

Parameters help

Name Type
_setToken
ISetToken help

Properties

Visibility help internal
Mutability help view
Source Code
function isSetPendingInitialization(ISetToken _setToken)
  internal
  view
  returns (bool)
{
  return _setToken.isPendingModule(address(this));
}

internal ModuleBase.isSetManager keyboard_arrow_up

Parameters help

Name Type
_setToken
ISetToken help
_toCheck
address help

Properties

Visibility help internal
Mutability help view
Source Code
function isSetManager(ISetToken _setToken, address _toCheck)
  internal
  view
  returns (bool)
{
  return _setToken.manager() == _toCheck;
}

internal ModuleBase.isSetValidAndInitialized keyboard_arrow_up

Parameters help

Name Type
_setToken
ISetToken help

Properties

Visibility help internal
Mutability help view
Source Code
function isSetValidAndInitialized(ISetToken _setToken)
  internal
  view
  returns (bool)
{
  return
    controller.isSet(address(_setToken)) &&
    _setToken.isInitializedModule(address(this));
}

internal ModuleBase.getNameHash keyboard_arrow_up

Parameters help

Name Type
_name
string help

Properties

Visibility help internal
Mutability help pure
Source Code
function getNameHash(string memory _name) internal pure returns (bytes32) {
  return keccak256(bytes(_name));
}

internal ReentrancyGuard.constructor keyboard_arrow_up

Parameters help

This function has no parameters.

Properties

Visibility help internal
Mutability help transaction
Source Code
constructor() internal {
  _status = _NOT_ENTERED;
}