Function _handlePayout( address recipient, uint256 payout_, ERC20 payoutToken_, uint48 vesting_) internal
INTERNAL FUNCTION
Intended behavior.
This function is supposed to handle the payout of
payoutToken_
to the user if vesting time is zero or to mint the corresponding number ofBond
tokens with the possibility of withdrawal after a certain amount of time.It should transfer
payoutToken_
torecipient_
directly if there is no vesting timeIt should mint
Bond
tokens torecipient_
if vesting time isn’t zeroIf there isn’t
Bond
token for currentpayoutToken_
andexpiry
time, it should be created before mint
Negative behavior.
It shouldn't mint and transfer zero value of tokens.
It shouldn't mint and transfer to zero address.
It shouldn't transfer tokens if there are not enough of them on the contract balance. (The
safeTransfer
call will be reverted)it’s not supposed to mint if vesting is
==0
or transfer payout if vesting is!=0
.
Preconditions.
There is enough
payoutToken_
for transfer torecipient
Assumes that the token that is supposed to be minted exists. Otherwise, it tries creating it.
Assumes that
getTokenId
works well and there are no issues with how it retrieves theid
.Assumes that the
tokenId
is unique and no multiplepayoutToken_, expiry
pairs can exist.
Postconditions.
if vesting time is zero
payoutToken_.balanceOf(recipient_) <= balanceBefore+payout
andpayoutToken_.balanceOf(BondFixedTermTeller) >= balanceBefore-payout
andrecipient_
shouldn’t get additionalBond
tokensif vesting time isn’t zero
BondFixedTermTeller.balanceOf(recipient) ≤ balanceBefore+payout
and shouldn't get additionalpayoutTokens
if the
bondToken
wasn’t deployed beforehand, now it should be.
Inputs.
Since the function is internal, conclusions were made based on the analysis of the calling function.
address recipient_ - controlled
uint256 payout_ - it is partially controlled because it is calculated based on the controlled
amount
value. but this function should not care whether this value is calculated correctly.ERC20 payoutToken_ - partially controlled, the caller selects any market to which the payoutToken address is linked, that is, the caller can select any address from those already linked to the markets.
uint48 vesting_ - it is not controlled because it is a market setting.
Examine all function calls the function makes.
a. Call to
_mintToken(recipient, tokenId, payout_);
callsmint(to, tokenId_, amount_, bytes(""))
callsERC1155TokenReceiver(to).onERC1155Received
If the calling contract is a contract, then it will be called.What is controllable? (callee, params, return value):
recipient
- controlled, and ifrecipient
is the contract address, it will be called by mint hook ^ see above;tokenId
- partially controlled, calculated based onpayoutToken_
address andexpiry
value; they assume it’s unique and no multiplepayoutToken_, expiry
pairs can exist;payout_
- partially controlled, calculated based onamount_
If return value controllable, how is it used and how can it go wrong? There is no return value.
What happens if it reverts or tries to reenter? this function is called only at the end of the
purchase
function, and all important functions includepurchase
havenonReentrant
protection. it looks like it can't be used, but it's better to keep this possibility in mind; it will be reverted in the following situations; if addressrecipient == address(0)
; ifERC1155TokenReceiver(to).onERC1155Received
will return wrong selector or reject the call inside
b. Call to
uint256 tokenId = getTokenId(payoutToken_, expiry)
What is controllable? (callee, params, return value): ERC20 payoutToken_ - partially controlled, the caller selects any market to which the payoutToken address is linked, that is, the caller can select any address from those already linked to the markets.; expiry - it is not controlled
If return value controllable, how is it used and how can it go wrong? if there were possible collisions between real and fake tokens, then it would be possible to deposit dummy tokens and withdraw real ones; if there is any way to bypass the encoding and calculation, it would be possible to create an additional
payoutToken, expiry_
pair that would have the sametokenId
What happens if it reverts or tries to reenter? No problems
c. Call to
_deploy(tokenId, payoutToken_, expiry)
What is controllable? (callee, params, return value): uint256 tokenId - it is not controlled; ERC20 payoutToken_ - partially controlled, the caller selects any market to which the payoutToken address is linked, that is, the caller can select any address from those already linked to the markets; expiry - it is not controlled
If return value controllable, how is it used and how can it go wrong? there is no return value
What happens if it reverts or tries to reenter? No problem
d. Call to
payoutToken_.safeTransfer(recipient_, payout_)
What is controllable? (callee, params, return value): payoutToken* - partially controlled, the caller can select any address from those already linked to the markets; payout* - controlled
If return value controllable, how is it used and how can it go wrong? there is no return value
What happens if it reverts or tries to reenter? will be reverted if the current contract doesn't have enough tokens