Function purchase( address recipient_, address referrer_, uint256 id_, uint256 amount_, uint256 minAmountOut_ ) external nonReentrant
Intended behavior.
allows users to exchange the
amount
ofquoteToken
topayoutToken
.calculates the fee values for
referrer_
if it exists and forProtocol
if protocolFee was set.calculate the
payout
value forauctioneer
with passedid_
foramountLessFee
value.saves fee values for later withdrawal
transfer from the
msg.sender
theamount
of thequoteToken
token to contract address.over
callbackAddr
address or directly transfer thepayout
value of thepayoutToken
from marketowner
to contract address.to
callbackAddr
address or directly transfer theamountLessFee
value of thequoteToken
from contract address toowner
of market.transferring tokens directly to the
recipient_
address if it isInstantSwap
or mint for therecipient_
thepayout
amount of Bonds tokens which will be blocked for exchange to thepayoutToken
before theexpiry
time.
Negative behavior.
msg.sender
sent an insufficient number of thequoteToken
tokenspayout
less thenminAmountOut_
the market for the
id_
doesn't exist; assure that ingetMarketInfoForPurchase
fromBondBaseSDA
the market owner doesn’t have enough
payoutToken
tokensif it isn’t
InstantSwap
thenrecipient_
shouldn't receivepayoutToken
, but only Bonds tokensif it is
InstantSwap
thenrecipient_
shouldn’t receive the Bonds tokens, but onlypayoutToken.
Shouldn’t allow transferring on behalf of other users.
Preconditions.
The market for the corresponding
id_
should be registered inside the_aggregator
contract, to do this, the address of theAuctioneer
which store the markets must be whitelisted inside_aggregator
contract.msg.sender
should have enoughquoteToken
tokens ≥amount
market owner should have enough
payoutToken
≥payout
Postconditions.
if
callbackAddr != address(0)
, thenamountLessFee
value ofquoteToken
tokens should be successfully sent tocallbackAddr
msg.sender
balance ofquoteToken
decreased byamount
quantity of tokensowner
balance ofpayoutToken
decreased bypayout
quantity of tokensif
InstantSwap
thenrecipient_
should successfully receive thepayout
value ofpayoutToken
if it isn’t
InstantSwap
thenrecipient_
received thepayout
value of Bond tokens with the corresponding non-zero expiry timerewards
increased for non-zeroreferrer_
bytoReferrer
amount ofquoteToken
tokensrewards
increased for_protocol
by non-zerotoProtocol
amount ofquoteToken
tokens
Inputs.
address recipient_ - controlled. can be any address
address referrer_ - controlled. can be any address
uint256 id_ - controlled. used to select market
uint256 amount_ - controlled, amount of
quoteToken
whichmsg.sender
should transfer to contract, there is a check inside the_handleTransfers
functionuint256 minAmountOut* - controlled, min amount of
payout
tokens, whichrecipient*
will receive, there is a check inside theauctioneer.purchaseBond
function
Examine all function calls the function makes.
a. Call to
IBondAuctioneer auctioneer = aggregator.getAuctioneer(id_)
What is controllable? (callee, params, return value):
id_
- controlled,msg.sender
can choose any createdauctioneer
by theirid_
value. only a whitelisted contract can become anauctioneer
.If return value controllable, how is it used and how can it go wrong? if
auctioneer
for currentid_
doesn’t exist, thengetAuctioneer
function will returnaddress(0)
otherwise will returnauctioneer
address which has created the market.What happens if it reverts or tries to reenter?
aggregator
- is a trusted contract address, no problems here
b. Call to
auctioneer.getMarketInfoForPurchase(id_)
What is controllable? (callee, params, return value):
id_
- controlled. it is unique market identificationIf return value controllable, how is it used and how can it go wrong? address owner - market owner address can be any user. should transfer the necessary amount of
payoutToken
; address payoutToken - controlled, any user can create a market with any token address; address quoteToken - controlled, any user can create a market with any token address; uint48 vesting - controlled, any user can create a market with any vesting time. However, the values are controlled, the user must transfer the appropriate number of tokens for exchange. if these are dummy tokens, users will not exchange them.What happens if it reverts or tries to reenter? No problem
c. Call to
auctioneer.purchaseBond(id_, amountLessFee, minAmountOut_)
What is controllable? (callee, params, return value):
id_
- controlled;amountLessFee
- partially controlled because it's an amount value minus the fee values;minAmountOut_
- controlled, ifpayout
less thanminAmountOut_
, transaction should be rejected.If return value controllable, how is it used and how can it go wrong? as a result of calculation errors, the user may receive more
payout
tokens than he should; ifpayout
value is less thanminAmountOut_
, the transaction should be canceled.What happens if it reverts or tries to reenter? Can revert in case if
payout
value is less thanminAmountOut_
, expected behavior.
d. Call to
handleTransfers(id, amount_, payout, toReferrer + toProtocol)
What is controllable? (callee, params, return value):
id_
- controlled;amount_
- controlled, there is a check thatmsg.sender
transfer no less thanamount_
to contract address;payout
- uncontrolled, there is a check that owner transfer no less thanpayout
to contract address;toReferrer + toProtocol
- uncontrolledIf return value controllable, how is it used and how can it go wrong?
What happens if it reverts or tries to reenter?
f. Call to
handlePayout(recipient, payout, payoutToken, vesting)
: full review in the description ofBondFixedTermTeller.sol