friend_tech can only buy 1 key in the first transaction?

Original link: https://igaojin.me/2023/09/19/friend-tech-%E7%AC%AC%E4%B8%80%E7%AC%94%E4%BA%A4%E6%98% 93%E5%8F%AA%E8%83%BD%E4%B9%B0-1-%E4%B8%AAkey/

background

Someone in the group said that friend tech can only buy 1 for the first transaction?

I refuted him at the time. After all, I am considered someone who has read the contract code of friend tech. There is no limit to the contract and you can only buy one transaction.

Stop talking nonsense and just look at the code

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
 function buyShares ( address sharesSubject, uint256 amount ) public payable {
uint256 supply = sharesSupply[sharesSubject];
require (supply > 0 || sharesSubject == msg.sender, "Only the shares' subject can buy the first share" );
uint256 price = getPrice(supply, amount);
uint256 protocolFee = price * protocolFeePercent / 1 ether;
uint256 subjectFee = price * subjectFeePercent / 1 ether;
require (msg.value >= price + protocolFee + subjectFee, "Insufficient payment" );
sharesBalance[sharesSubject][msg.sender] = sharesBalance[sharesSubject][msg.sender] + amount;
sharesSupply[sharesSubject] = supply + amount;
emit Trade(msg.sender, sharesSubject, true , amount, price, protocolFee, subjectFee, supply + amount);
(bool success1,) = protocolFeeDestination.call{ value : protocolFee}( "" );
(bool success2,) = sharesSubject.call{ value : subjectFee}( "" );
require (success1 && success2, "Unable to send funds" );
}

At first glance, the code is very simple. The only limitation is this sentence.

require(supply > 0 || sharesSubject == msg.sender, "Only the shares' subject can buy the first share");

What this sentence means is that newly registered users can only make their first purchase. There is no limit on how many keys they can buy…

not that simple

So why do others still say that you can only buy 1 key?

Be more rigorous and just use forge to simulate buying and you will know.

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 import {TestHarness} from "../../TestHarness.sol" ;

interface iFriendtech {
function buyShares ( address sharesSubject, uint256 amount ) external payable ;
}

contract fuck_friend_tech is TestHarness {
iFriendtech friendtech = iFriendtech( 0xCF205808Ed36593aa40a44F10c7f7C2F67d4A4d4 );

function setUp ( ) external {
cheat.createSelectFork( "base" , 4 _119_770);
cheat.deal(address( this ), 100 ether);
}

function test_attack ( ) external {
friendtech.buyShares{ value : 100 ether}(address( this ), 2 );
}

receive() external payable {}
}

Don’t tell me, it really failed…The error reported is [FAIL. Reason: Arithmetic over/underflow] test_attack() (gas: 3252)

Looking back at the code of buyShares , the only suspicious point is getPrice

 1
2
3
4
5
6
7
8
9
 function getPrice ( uint256 supply, uint256 amount ) public view returns ( uint256 ) {
uint256 sum1 = supply == 0 ? 0 : (supply - 1 ) * (supply) * ( 2 * (supply - 1 ) + 1 ) / 6 ;
uint256 sum2 = supply == 0 && amount == 1
? 0
: (supply - 1 + amount) * (supply + amount) * ( 2 * (supply - 1 + amount) + 1 ) / 6 ;

uint256 summation = sum2 - sum1;
return summation * 1 ether / 16 _000;
}

The problem occurs in sum2… supply-1+amount. There is an error here… After all, the solidity language is a bit silly, and 0-1=-1 directly overflows…

Well, it turns out that the reason why you can’t buy more than one for the first time is because the team wrote a bug… The correction is also very simple, just + first and then -.

(supply - 1 + amount) * (supply + amount) * (2 * (supply - 1 + amount) + 1) / 6;
(supply + amount - 1) * (supply + amount) * (2 * (supply + amount - 1) + 1) / 6;

Author of this article : Gao Jin
Address of this article : https://igaojin.me/2023/09/19/friend-tech-The first transaction can only buy -1-key/
Copyright statement : Please indicate the source when reprinting!

This article is reproduced from: https://igaojin.me/2023/09/19/friend-tech-%E7%AC%AC%E4%B8%80%E7%AC%94%E4%BA%A4%E6%98% 93%E5%8F%AA%E8%83%BD%E4%B9%B0-1-%E4%B8%AAkey/
This site is only for collection, and the copyright belongs to the original author.