Solidity작업은 끝났습니다.
문제는 마이그레이션을 할수가 없습니다....
Character
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.0;
import "./libraries/Token.sol";
import "./libraries/NFT.sol";
interface char {
event NewUser(
address indexed owner,
uint256 indexed Pow,
uint256 indexed limit
);
event TokenPurchased(
address indexed account,
uint256 indexed amount,
address indexed server
);
event Token_Transfer_All(address[] indexed account, uint256 indexed value);
event Token_Sell(
address indexed account,
uint256 indexed amount,
address indexed server
);
event token_transferError(address account, uint256 amount);
}
contract check_User {
mapping(address => bool) internal checkUser;
address internal owner;
modifier isOwner(address _address) {
require(checkUser[_address] == true);
_;
}
modifier onlyOwner() {
require(owner == msg.sender, "Not adming address!");
_;
}
}
contract Character is char, check_User {
mapping(address => Characters) private _Character;
Token private gold;
// 0xB202e69304628a9C19928960A042401AC5FFB37C
NFT private nft;
// 0x457FBe2b16f754cf3bE664131B12afA05bc42382
uint256 PowFee = 30;
uint256 limitFee = 50;
struct Characters {
uint32 Pow;
uint32 limit;
}
modifier check_balance(address _address, uint256 value) {
require(gold.balanceOf(_address) >= value);
_;
}
constructor(address _token, address _NFT) {
gold = Token(_token);
nft = NFT(_NFT);
owner = msg.sender;
}
function buyTokens() public payable {
require(msg.sender != address(0x0), "No Existed address");
// 단위 계산이 wei로 들어오기 때문에 나눠준다.
uint256 tokenAmount = msg.value / 100000000000;
Gold_transfer_eachOther(msg.sender, address(gold), tokenAmount);
// 괜히 delegatecall을 사용해보고 싶어서 만지작 대다가... onlnyOwner이라는 문제와 msg.sender이라는 문제에 막혀서 그냥 다른 함수를 사용하였습니다.
// (bool success, ) = address(this or gold).delegatecall(abi.encodeWithSignature("transfer(address,uint256)", msg.sender, tokenAmount));
// if(!success){
// emit token_transferError(msg.sender, tokenAmount);
// revert();
// }
// Uniswap에서 pair pool을 만들떄에 CA값을 활용하는 것을 보고 처음에는 payable(address(gold))로 적고 시도를 해보았다.
// 근데 CA에는 transfer가 안된다는 것을 까먹고 계속 뭐가 문제인지를 파악하지 못했다...
// pair pool이라는 CA값에 너무 집중했는지 쓸데 없는 시간을 낭비했던 부분;;
// Swap이라고 부르기도 좀 그렇지만 유동성문제를 해결할수 없기 떄문에 활용가능한 범위에서만 코드를 적었습니다.
owner.transfer(msg.value);
emit TokenPurchased(msg.sender, tokenAmount, address(gold));
}
function sellTokens(uint256 value) public payable {
require(msg.sender != address(0x0), "No Existed address");
// Token을 CA주소로 반환하는 행위
Gold_transfer_eachOther(address(gold), msg.sender, value);
// wei로 들어올떄 100000000000만큼 나누어 줌
// 나갈떄에는 Token의 양에 100000000000만큼 곱해주면됨
uint256 Wei_amount = value * 100000000000 wei;
msg.sender.transfer(Wei_amount);
emit Token_Sell(msg.sender, msg.value, address(gold));
}
function NFT_minting(string memory URI) public isOwner(msg.sender) {
// 아이템을 뽑을떄 실행시킬 트랜잭션
nft.mintNFT(msg.sender, URI);
}
function NFT_transfer(
address buyer,
uint256 Price,
uint256 NFT_index
) public isOwner(msg.sender) {
require(buyer != address(0), "Not Existed address");
require(Gold_balanceOf(buyer) >= Price, "Buyer is not having Price");
require(
nft.ownerOf(NFT_index) == msg.sender,
"The owner of this NFT is not msg.sender"
);
// 이전에는 1분마다 하루가 지난 거래를 확인하여 거래를 진행하였지만 이번에는
// 사용자가 직접 원할떄에 버튼을 눌러서 거래가 되게 할 예정
// 단순히 token 거래와 NFT이동만 시켜주면 된다.
// 일단 토큰 거래를 해준다
Gold_transfer_eachOther(msg.sender, buyer, Price);
// 그후 NFT거래를 해준다.
NFT_transferFrom(msg.sender, buyer, NFT_index);
}
function NFT_transferFrom(
address owner,
address buyer,
uint256 NFT_index
) internal {
nft.transferFrom(owner, buyer, NFT_index);
}
function Gold_transfer_eachOther(
address recipient,
address sender,
uint256 value
) internal {
// 이 부분은 CA와 사용자간의 거래를 하는 부분
gold.transfer_To_CA(recipient, sender, value);
}
function Gold_transfer(address to, uint256 amount)
public
isOwner(to)
onlyOwner
{
// 서버계정에서 사람들에게 token을 지급하는 부분
gold.transfer(to, amount);
}
function Gold_mintAll(address[] memory account, uint256 amount)
public
onlyOwner
{
for (uint256 i = 0; i < account.length; i++) {
require(checkUser[account[i]] != false, "not Existed User!");
// 이런 검증 로직이 많아지면 가스비 소모가 증가하지만
// 검증하는 부분을 뺴놓을수가 없어서...
}
gold.transfer_all(account, amount);
}
function Char_makeCharacter(address _address)
public
onlyOwner
returns (bool)
{
// 기존에 없는 캐릭터여야 한다.
// 서버가 실행하여 캐릭터를 만들어 준다.
require(checkUser[_address] == false);
checkUser[_address] = true;
Characters storage character = _Character[_address];
character.Pow = 1;
character.limit = 300;
emit NewUser(_address, character.Pow, character.limit);
return true;
}
function Char_IncreaseLimit()
public
isOwner(msg.sender)
check_balance(msg.sender, limitFee)
{
// 자신이 가지고 있는 토큰을 gold의 CA주소에 반환해야 한다.
Gold_transfer_eachOther(address(gold), msg.sender, limitFee);
Characters storage character = _Character[msg.sender];
character.limit += 300;
}
function Char_IncreasePow()
public
isOwner(msg.sender)
check_balance(msg.sender, PowFee)
{
// 자신이 가지고 있는 토큰을 gold의 CA주소에 반환해야 한다.
Gold_transfer_eachOther(address(gold), msg.sender, PowFee);
Characters storage character = _Character[msg.sender];
character.Pow += uint32(Char_getStatus());
}
function Char_getPow(address _address)
public
view
isOwner(_address)
returns (uint32)
{
Characters memory character = _Character[_address];
return character.Pow;
}
function Char_getLimit(address _address)
public
view
isOwner(_address)
returns (uint32)
{
Characters memory character = _Character[_address];
return character.limit;
}
function Char_getUser(address _address)
public
view
isOwner(_address)
returns (Characters memory)
{
return _Character[_address];
}
function Char_getRandomNumber() internal view returns (uint256) {
// 오라클적인 문제점을 해결하기 위해서
// 계속 변화할수 있는 tokenCA가 가지고 있는 토큰의 양을 인자르 넘겨 주엇다
// token트랜잭션에 따라서 계속 변화할 것이기 떄문에
return
uint256(
keccak256(
abi.encodePacked(
block.timestamp,
Gold_balanceOf(address(gold))
)
)
) % 100;
}
function Char_getStatus() private view onlyOwner returns (uint256) {
// 이 함수는 따로 랜덤한 값을 받기 위해서 사용을 해야 하기 떄문에 public로 선언
// 어차피 서버 계정만이 사용할 함수
return Char_getRandomNumber() % 10;
}
function Gold_balanceOf(address _address) public view returns (uint256) {
return gold.balanceOf(_address);
}
function getNFT_List(address owner)
public
view
onlyOwner
isOwner(owner)
returns (string[] memory)
{
// 사용자가 소지한 모든 NFT를 받아오는 함수
string[] memory NFT_List = new string[](nft.balanceOf(owner));
uint256 index = 0;
for (uint256 i = 0; i < nft.totalNFTAmount(); i++) {
if (nft.getOwner(i) == owner) {
NFT_List[index] = (nft.getTokenURIs(i));
index++;
}
}
return NFT_List;
}
}
흠... 초기에는 뜯어 고치는 마이그레이션 작업이 별로 시간이 많이 소요되지 않고 손쉽게 해결이 될줄 알았습니다..
하지만 새롭게 작성하는 것보다 기존에 있던것을 뜯어 고치는 작업이 상당히 더 어렵다는걸 알게 되는 시간이였습니다...
또한 부가적으로 코드를 구조적으로 짜임새 있게 잘 적어야 할꺼 같습니다.
물론 중간중간 집중을 하여 짜임새 있게 작성하였다고 생각하였던 부분도 있지만 다른 부분에서는 이러한 부분을 적용하지 못했습니다.
배운 부분
- 코드를 구조적으로 작성을 하여 후에 수정이 필요하다면 원활하게 적용하자!
- 오만하지 말자... (요즘 이런 생각이 드는데 아직 많이 배워야 하는 사람이다~~!!)