일단 solve() 함수를 살펴보면
function solve(uint256 _gameId) external payable {
uint256 _userLevel = getUserLevel((tx.origin), _gameId);
require(_userLevel == 2, "not max level");
require(msg.value >= 1e18, "mint price is 1 eth");
solved = 1;
}
다음과 같이 2가지 조건을 통과해야 문제를 풀 수 있다
근데 문제에서 준 주소의 밸런스를 확인해보면 10이더를 제공해준다. 따라서 level == 2 를 달성하는데 포커스를 둔다
function levelUp(uint256 _gameId) external {
UserInfo storage user = users[msg.sender];
uint256 _userLevel = user.level[_gameId];
_isMaxLevel(_userLevel);
uint256 _userExp = user.exp[_gameId];
uint256 _userExpCap = user.expCap;
require(_userExp >= _userExpCap, "not enough exp");
user.level[_gameId] += 1;
user.exp[_gameId] = _userExp - _userExpCap;
user.expCap = _getLevelExpCap(_userLevel + 1);
}
levelUp 하는 함수를 살펴보면 exp가 필요한 것을 확인할 수 있다.
exp를 올릴 수 있는 방법을 찾아보자
function addNGReferral(address _referral) external {
UserInfo storage user = users[msg.sender];
require(!user.ng_referral[_referral], "already referral");
uint256 _activeUser = _isEligible(_referral);
int256 _rb;
assembly {
if extcodesize(_referral) { revert(0, 0) }
switch _activeUser
case 0 { _rb := sub(0, 1) }
default { _rb := add(0, 1) }
}
user.ng_referralBonus += _rb;
}
addNGReferral() 함수를 살펴보면 assembly 쪽에서 _activeUser 의 값을 0으로 만들면 _rb를 -1로 만들 수 있는 것을 확인했다
function _isEligible(address _user) internal view returns (uint256) {
return payable(_user).balance >= 1e18 ? 0 : 1;
}
_isEligible() 함수를 살펴보면 이더가 1개 이상있을경우 0을 반환한다. 근데 문제에서 10이더를 제공해주기 때문에 이 값을 0이 반환되고 최종적으로 _rb == 1 이 될 것이다.
그 후, feed() 함수를 호출하고
function feed(uint256 _gameId) external actionTotalValidation(_gameId) {
UserInfo storage user = users[msg.sender];
GameInfo storage game = user.games[_gameId];
uint256 _userLevel = user.level[_gameId];
require(!_isActionEnable(_gameId), "only one feed per round");
game.actionGuage -= 1;
user.exp[_gameId] += calculateActionExp(_userLevel, GameAction.Feed, 0);
game.actionEnable = true;
game.curAction = GameAction.Feed;
}