BONK Token Contract Audit & Review

The BONK token contract is relatively simple and easy to understand. In the following sections, it is explained in detail and step by step, so that everyone can verify it for themselves.

The official token contract can be found here and as a copy in the following section.

The code begins with a version definition, which determines which Solidity version the smart contract is based on and thus which functions and libraries can be used.

Next there is an interface “Callable”, which contains only one function. This function is the “tokenCallback” function and allows to check if a receiver of a transaction containing data (e.g. when executing a function of a smart contract) gives an accepting response. This is used later in the function “transferAndCall”.

Now the main part of the code begins, namely the implementation of the actual BONK token. It starts with a class “contract Bonk” and some variables:

  • FLOAT_SCALAR : This is the value to be multiplied or divided by the parameter to avoid rounding or decimal point errors, as Solidity has no decimal places.
  • INITIAL_SUPPLY : This is the amount of BONK tokens that are created when the smart contract is issued and therefore exist initially.
  • STAKE_FEE : This value determines the fee that is charged for each transfer of BONK tokens.
  • MIN_STAKE_AMOUNT : This value defines the minimum amount of BONK tokens needed to stake BONK tokens.

All the above mentioned variables are “constant” and “private”, which means that they can never be changed and are only known within “contract Bonk”. Next are three more variable assignments, but they are “public”, meaning that they are readable by external classes and smart contract. They cannot be overwritten either, because they are also “constant”.

Next, two struct declarations are defined. These act like own sub-classes and it is therefore possible to store the balance or the staked amount for each holder in the smart contract.

The “struct User” is exactly responsible for this:

  • bool whitelisted : Is the current wallet address whitelisted?
  • uint256 balance : The amount of BONK token the current wallet address is holding.
  • uint256 staked : The amount of BONK token the current wallet address is staking in the smart contract.
  • mapping(address => uint256) allowance : An array that stores how much BONK tokens another address is eligable to transfer from the current wallet address.
  • int256 scaledPayout : The amount of dividends in BONK tokens of the current wallet address scaled up by FLOAT_SCALAR.

The “struct Info” is responsible for the following:

  • uint256 totalSupply : The amount of BONK tokens in existance.
  • uint256 totalStaked : The amount of BONK tokens currently staked in the smart contract.
  • mapping(address => User) users : An array that stores a “struct User” for each wallet address which received BONK tokens at any time.
  • int256 scaledPayoutPerToken: The amount of dividends in BONK tokens you would receive per BONK token scaled up by FLOAT_SCALAR.
  • address admin : The wallet address of the founder / admin of the smart contract. Only he can call specific critical functions.

The “Info private info” is declaring a private “struct Info” at deployment of the smart contract.

These events are only there to tell the calling system, such as Metamask, what transaction has just been executed. For each event there are several functions, which are described in detail below.

The function “constructor” is, as the name suggests, no ordinary function, because it is automatically called once when the class “contract Bonk” is created, i.e. when the smart contract is deployed, and defines a few basic parameters and variables such as:

  • info.admin : Sets the smart contract deployer wallet address as admin.
  • info.totalSupply : Sets the total supply at the hardcoded INITIAL_SUPPLY.
  • info.users[msg.sender].balance : Sets the balance of the smart contract deployer / admin at INITIAL_SUPPLY and therefore the deployer initially holds 100% of the BONK tokens in existance at that time.
  • emit Transfer : Triggers the “Transfer”-event to tell e.g. Metamask or Etherscan that at deployment there is a transfer of the entire BONK token amount in existance from 0x0 to the smart contract deployer (same as a mint).
  • whitelist(msg.sender, true) : Whitelists the contract deployer (his wallet address).

Then there are two “external” functions, which means that they can only be accessed from outside this smart contract. These are used, for example, for the website and each of them calls up a function which is “internal”, that means they are only known within the smart contract.

The function “collect” checks if the caller (wallet address) has any claimable dividends. If so, those dividends get added to the “scaledPayout” and “balance” of the user and the Transfer and Collect event will be triggered. If not, nothing will happen.

These two functions do exactly the same thing only under a different name. In both cases a certain amount of BONK tokens (_tokens) is deducted from the callers balance, whereby it is of course checked beforehand whether this is possible, and made available to the staking pool. So these functions are more or less a donation function. Why they exist twice, I cannot say. Both functions are never called by the website and are probably only used to allow the team to donate a part of their BONK tokens to stakers.

The following three functions are standard functions. The first “transfer” calls an internal “_transfer” function from external with the respective parameters to send from caller to “_to” the quantity of “_tokens” of BONK tokens.

The “approve” function allows the “_spender” wallet address to send the number of “_tokens” to BONK tokens from the caller wallet.

The function “transferFrom” is an extension of the first of these three functions and has parameters for the recipient and the number of BONK tokens to be sent as well as the sender. First of all it is checked if the caller has the rights to send this amount of BONK tokens from the “_from” wallet.

The function “transferAndCall” is called in case the caller sends BONK tokens to another smart contract and wants to execute a certain code there (e.g. a function). This code is transmitted with “bytes calldata _data”. In this function the interface mentioned at the beginning of this article is also used.

The function “bulkTransfer” transfers, as the name suggests, a certain number of BONK tokens to a list of recipients. With each transfer it is checked if the sender (the caller) still holds enough BONK tokens to perform the transfer.

The function “whitelist” does exactly what you expect it to do when you read the function name. It sets the “whitelist” status of a submitted wallet address (_user) to “_status” (either true or false). Of course only the admin can call this function.

The following functions are only for retrieving certain information and values from the smart contract. This can be seen from the fact that all functions are “public”, i.e. can be called up from anywhere, and “view”, i.e. only return visual information. These are used, for example, to display on the website the number of staked BONK tokens in the smart contract or the dividends of a particular user (i.e. his wallet address).

The following three functions are all “internal” and start with a “_”. This means that these functions can only be called from within the class “contract Bonk”.

The first function is “_transfer”, which sends a certain amount of BONK tokens (_tokens) from a certain wallet (_from) to a certain wallet (_to). Of course it is checked at the beginning if the sender has enough BONK tokens. The check whether the caller has the rights to send tokens from the wallet of “_from” is taken up in the respective calling public functions, which were already described above. Otherwise, the fee (STAKE_FEE) will be deducted from the transferred amount and the respective variables will be adjusted accordingly.

Last but not least there are the two internal functions “_stake” and “_unstake” which, as their names suggest, are used to start and end a stake. With the “_stake” function, a certain amount of BONK tokens (_amount) is deducted from the callers wallet, credited to his staked BONK amount and sent to the BONK smart contract. There are no fees for this, but it is checked whether the quantity to be staked at least meets the minimum quantity. In the “_unstake” function, the same principle is used, but backwards, with the difference that when the BONK tokens are paid out from the smart contract to the caller, a fixed fee of 9% is charged, which remains in the smart contract and acts as a dividend for the other stakers.

And so we have reached the end of the smart contract for the BONK token. I hope it is now much easier to understand how the smart contract works and that everything has been securely programmed. If you have any further questions please contact an admin in our telegram chat.

This article was written by @robster97.

PS: The lines that were left out between the screenshots are only spaces and have no meaning.