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 ofBondtokens 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
Bondtokens torecipient_if vesting time isn’t zeroIf there isn’t
Bondtoken for currentpayoutToken_andexpirytime, 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
safeTransfercall will be reverted)it’s not supposed to mint if vesting is
==0or transfer payout if vesting is!=0.
Preconditions.
There is enough
payoutToken_for transfer torecipientAssumes that the token that is supposed to be minted exists. Otherwise, it tries creating it.
Assumes that
getTokenIdworks well and there are no issues with how it retrieves theid.Assumes that the
tokenIdis unique and no multiplepayoutToken_, expirypairs can exist.
Postconditions.
if vesting time is zero
payoutToken_.balanceOf(recipient_) <= balanceBefore+payoutandpayoutToken_.balanceOf(BondFixedTermTeller) >= balanceBefore-payoutandrecipient_shouldn’t get additionalBondtokensif vesting time isn’t zero
BondFixedTermTeller.balanceOf(recipient) ≤ balanceBefore+payoutand shouldn't get additionalpayoutTokensif the
bondTokenwasn’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
amountvalue. 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).onERC1155ReceivedIf the calling contract is a contract, then it will be called.What is controllable? (callee, params, return value):
recipient- controlled, and ifrecipientis the contract address, it will be called by mint hook ^ see above;tokenId- partially controlled, calculated based onpayoutToken_address andexpiryvalue; they assume it’s unique and no multiplepayoutToken_, expirypairs 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
purchasefunction, and all important functions includepurchasehavenonReentrantprotection. 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).onERC1155Receivedwill 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 sametokenIdWhat 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