14

Looking at all the latest shitcoins' Smart Contract code on Binance Smart Chain, there's a lot of common,recurring themes because most of each project's code is mostly copy-pasted. The code is also completely uncommented, which makes it a pain to understand what's what.

Most of these contacts use two different types of variables for their internal token calculations, 1 called t and one called r. For example, on TrustPad's smart contract (available here: bscscan link):

    mapping(address => uint256) private _rOwned;
    mapping(address => uint256) private _tOwned;
    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private constant MAX = ~uint256(0);
    uint256 private constant _tTotal = 100 * (10 ** 6) * (10 ** 9);
    uint256 private _rTotal = (MAX - (MAX % _tTotal));
    uint256 private _tFeeTotal;
    uint256 private _tFeePercent = 2;

Anybody got any idea what the r and t mean, and why they maintain _tOwned and _rOwned, _tTotal and _rTotal, etc?

3
  • Same question (though no answers): ethereum.stackexchange.com/questions/97782/… May 9, 2021 at 9:24
  • 1
    Haven't looked into it, but probably something along the lines of "Automatic x% Distribution to Holders and Burn on Each Transaction"... May 9, 2021 at 9:26
  • 1
    @RichardHorrocks You're right that it has something to do with the mehcanic most of these coins called "reflection to holders", which incidentally starts with an r, but what's the t they also maintain for variables? t for tax? No idea! May 9, 2021 at 9:28

3 Answers 3

16

It' a bit of an algorithm, or really just some math, to to the balance of an account. Instead of using the default "tokenSupply".

Constants

Fee is 1% (assuming no burn, just a general 1% fee)

tTotal is totalSupply and literally never changes
rTotal starts at 127366483000000 and continuously subtracts or adds
currentRate 

Example:

You buy 100 Token as tAmount

>>>

Current Totals:
rTotal = 127366483000000
tTotal = 10000

currentRate = rTotal / tTotal
= 12736648300

Formula to get amount you will receive
> rTransferAmount = [rAmount] - [rFee]
[rAmount] = tAmount * currentRate
> 1273664830000 = 100 * 12736648300
[rFee] = tFee * currrentRate
> 127366483 = .01 * 12736648300

>>> 1273537463517 = [rAmount] - [rFee] = rTransferAmount

rTotal is updated to = rTotal - rTransferAmount 

balanceOf():

= rAmount / currentRate
> 

rAmount[me] is rAmount
rAmount = 1273537463517
currentRate = 12735374635.17

Balance: 100

...Someone else makes a transfer from x0 supply to buy 100 Tokens

rTotal = 126092945536483
tTotal = 10000

currentRate = rTotal / tTotal
= 12609294553.6483

Formula to get amount you will receive
> rTransferAmount = [rAmount] - [rFee]
rAmount = tAmount * currentRate
> 1260929455364.83 = 100 * 12609294553.6483
rFee = tFee * currrentRate
> 126092945.536483 = .01 * 12609294553.6483

>>> rTransferAmount = 1260803362419.293517

They now have 100

...Now check [me] balance after previous purchase


balanceOf():

= rAmount / currentRate

rAmount[me] is rAmount
rAmount = 1273537463517
currentRate = 12609294553.6483

Balance: 100.9998979799010304029995929297


...Now lets buy 100 more directly after checking balance
...this is the next transaction after the previous one

rTotal = 124832142174063.706483
tTotal = 10000

currentRate = rTotal / tTotal
= 12483214217.4063706483

Formula to get amount you will receive
> rTransferAmount = [rAmount] - [rFee]
rAmount = tAmount * currentRate
> 1248321421740.63706483 = 100 * 12483214217.4063706483
rFee = tFee * currrentRate
> 124832142.174063706483 = .01 * 12483214217.4063706483

>>> rTransferAmount = 1248196589598.463001123517

We now take our previous rAmount and add the rTransferAmount to update our rAmount

> rOwned[me] = rOwned[me] + rTransferAmount 
> 2521734053115.463001123517 = 1273537463517 + 1248196589598.463001123517

...Now check [me] balance after previous purchase


balanceOf():

= rAmount / currentRate

rAmount[me] is rAmount
rAmount = 2521734053115.463001123517
currentRate = 12483214217.4063706483

Balance: 202.00999591909607202719956134358


... now lets sell 100

rTotal = 123583945584465.243481876483
tTotal = 10000

currentRate = rTotal / tTotal
= 12358394558.4465243481876483

Formula to get amount you will receive
> rTransferAmount = [rAmount] - [rFee]
rAmount = tAmount * currentRate
> 1235839455844.65243481876483 = 100 * 12358394558.4465243481876483
rFee = tFee * currrentRate
> 123583945.584465243481876483 = .01 * 12358394558.4465243481876483

>>> rTransferAmount = 1235715871899.067969575282953517

We now take our previous rAmount and add the rTransferAmount to update our rAmount

(we are subtracting because we are selling)

> rOwned[me] = rOwned[me] - rTransferAmount 
> 1286018181216.395031548234046483 = 2521734053115.463001123517 - 1235715871899.067969575282953517

rTotal is updated to = rTotal - rTransferAmount 
122348229712566.17551230120004648 = 123583945584465.243481876483 - 1235715871899.067969575282953517

...Now check [me] balance after previous purchase

balanceOf():

= rAmount / currentRate

rAmount[me] is rAmount
rAmount = 1286018181216.395031548234046483
currentRate = 12358394558.4465243481876483

Balance: 104.06029481697096470326753341015

Example assumes a 1% fee with reflect and nothing else. Usually there is a fee that reflects and burns

6
  • 3
    Thanks for this answer, friend. Any reason you started rTotal at 127366483000000? May 14, 2021 at 8:35
  • @DimitrisSfounis rTotal is fixed & pre-determined constant _rTotal = (MAX - (MAX % _tTotal));
    – hack3r-0m
    May 22, 2021 at 18:05
  • 2
    @bob-linux: if you buy 100 token, and the total fee is 1%....and I think you will get 99 token in the end...am I correct? and when you calculate the balance, it seems that you don't care about how many token holders out there... why?
    – mc-tor
    Jul 17, 2021 at 9:57
  • I also have some doubts and there is not too much information on the internet. I think that is also because all of these coins are a clone of a previous one with same code, so the variable names are spread across all repos. Nov 4, 2021 at 22:24
  • 1
    Not exactly true: _rTotal is always decreasing in order to divide less between holders. Nov 14, 2021 at 3:04
3

Well _rTotal is simply Total Reflections and _rOwned refers to number of reflection a user owns. think of this way: we could set initial _rTotal to 100 to represent 100% and if your _rOwned value is 10, you own 10% of total reflections. in the constructor method you see after deployment of the contract, the whole reflections are transfered to the owner of the contract.

_rOwned[_msgSender()] = _rTotal;

using 100 as total reflection has a problem: solidity only supports integers and doesn't support floating point numbers, so we gotta somehow do it another way

If i am right, the reason they set _rTotal to a huge number is to make reflection very accurate and support as much floating points as possible (if i am wrong, correct me in comments), so if you own something like 0.00812301283120398912312836% of reflections, it should work accurately.

I hope i could explain it in a simple way

1

tTotal, which belongs to t-space, represents tokens in circulation or total supply of a token. On the other hand, rTotal, which belongs to r-space, is a reflected value of tTotal. The term “reflected” cannot be easily explained in words but one interpretation of rTotal is token supply in reserve.

tAmount: token amount that sender pays/transfers including tFee  • tFee: transfer fee (note: 10% was chosen arbitrarily)  • tTransferAmount: tokens that will get transferred to recipient  • tOwned[user]: User’s balance represented in t-space (only used by non-stakers)  • rOwned[user]: User’s balance represented in r-space

https://reflect-contract-doc.netlify.app/

Not the answer you're looking for? Browse other questions tagged or ask your own question.