[TIL] 2023-05-18 DAY43
GIT 주소 : https://github.com/dowoo303/SOLIDITY
오늘 배운것들
- TEST4 리뷰
1) 문제 리뷰
2) FixedDynamic 정적 동적 비교
3) Pop과 Delete 가스비 비교- TEST5 리뷰
1) 문제 리뷰
2) While
3) 배열뒤집기(ReversArray)
4) Bytes 길이측정 및 string으로 변환법- TEST6
각종 팁
receive() external payable{}는 스마트 컨트랙트가 To일 경우에만 사용한다.- new: 동적변수지만 일단은 길이를 정해놓은 정적으로 변화시킴
- mapping: 머클 패트리시아 트리 형태
- calldata: 진짜 memory: 카피해서 사용
- 동시스왑: (a[0], a[3]) = (a[3], a[0])
- bytes는 특별한 배열이다. bytes일때는 동적이지만 bytes[n]이라고 하면 정적으로 변한다.
회고
- 예상문제: 6진수로 표현해보기
- abi.encodePacked(a)를 이용하면 문자열 떼어내기 뿐만 아니라, 1bytes들을 입력받아서 하나의 문자열로 내보내기도 가능하다.
초기 설정에 신경을 써야한다.
왜 mapping(address => User) userList; 구조체를 값으로 하는 매핑을 안했지 ..?
-> 초기설정을 한 다음에 계속 그 처음의 초기설정으로 끼워맞추려는 경향이 있는데 초기설정도 바꾸는 유연함을 기르자.
contract Answer1 {
struct User {
uint number;
string name;
address account;
uint balance;
uint score;
}
mapping(address => User) userList;
uint count;
User[] public top4; // 일단 Dynamic(동적) 배열로 선언
User[4] public top4_2;
address payable owner;
constructor() payable {
// 0번 지갑 주소 : 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
owner = payable(0x5B38Da6a701c568545dCfcB03FcB875f56beddC4);
}
// * 유저 등록 기능 - 유저는 이름만 등록, 번호는 자동적으로 순차 증가, 주소도 자동으로 설정, 점수도 0으로 시작
function register(string memory _name) public {
userList[msg.sender] = User(count++, _name, msg.sender, msg.sender.balance, 0);
}
// * 유저 조회 기능 - 유저의 전체정보 번호, 이름, 주소, 점수를 반환.
function search(address _a) public view returns(User memory) {
return userList[_a];
}
// * 게임 참가시 참가비 제출 기능 - 참가시 0.01eth 지불 (돈은 smart contract가 보관)
// 동적배열
function gameIn() public payable {
require((userList[msg.sender].balance >= 10**16 && msg.value==0) || msg.value == 0.01 ether);
if(msg.value==0) {
userList[msg.sender].balance -= 10**16;
}
if(top4.length ==4) {
for(uint i=4;i>0;i--) {
userList[top4[i-1].account].score += 5-i;
}
delete top4;
}
top4.push(userList[msg.sender]);
}
// 고정(fixed)배열
function gameIn2() public payable {
require((userList[msg.sender].balance >= 10**16 && msg.value==0) || msg.value == 0.01 ether);
if(msg.value==0) {
userList[msg.sender].balance -= 10**16;
}
if(getLengthOfTop4()==4) {
for(uint i=4;i>0;i--) {
userList[top4[i-1].account].score += 5-i;
}
delete top4_2;
}
top4_2[getLengthOfTop4()] = userList[msg.sender];
}
/*
위의 gameIn2()를 modifier를 사용해본 버전
modifier isitFour {
if(getLengthOfTop4()==4) {
delete top4_2;
_;
}
_;
}
function gameIn2_2() public payable isitFour {
require((userList[msg.sender].balance >= 10**16 && msg.value==0) || msg.value == 0.01 ether);
if(msg.value==0) {
userList[msg.sender].balance -= 10**16;
}
top4_2[getLengthOfTop4()] = userList[msg.sender];
}*/
function getLengthOfTop4() public view returns(uint) {
// 고정배열의 초기값이 0인 것을 이용한다
for(uint i=0; i<4; i++) {
if(top4_2[i].account == address(0)) {
return i;
}
}
return 4;
}
// * 점수를 돈으로 바꾸는 기능 - 10점마다 0.1eth로 환전
function withdraw(uint _n) public {
// 10점 단위로 넣는다고 가정
require(_n%10==0 && userList[msg.sender].score >= _n);
userList[msg.sender].score -= _n;
payable(msg.sender).transfer(_n%10*0.1 ether);
}
// * 점수를 돈으로 바꾸는 기능 - 10점마다 0.1eth로 환전 (최대 금액 자동 환전)
function withdraw_All() public {
require(userList[msg.sender].score >= 10);
uint a = userList[msg.sender].score /10;
userList[msg.sender].score = userList[msg.sender].score%10;
payable(msg.sender).transfer(a*0.1 ether);
}
// * 관리자 인출 기능 - 관리자는 0번지갑으로 배포와 동시에 설정해주세요, 관리자는 원할 때 전액 혹은 일부 금액을 인출할 수 있음 (따로 구현)
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function ownerWithdraw(uint _n) public onlyOwner {
owner.transfer(_n*1 ether);
}
function ownerWithdrawAll() public onlyOwner {
owner.transfer(address(this).balance);
}
// * 예치 기능 - 게임할 때마다 참가비를 내지 말고 유저가 일정금액을 미리 예치하고 게임할 때마다 자동으로 차감시키는 기능.
function deposit() public payable {
userList[msg.sender].balance += msg.value;
}
}
for에서 조건문을 설정하기 애매할때 사용한다. 즉, 특정조건을 만족할 때까지 반복해야할 경우 사용한다.
while은 조건 1개만 설정해주면 된다. -> 그러므로 무한반복이 되지 않도록 주의해야한다.
형태: while(조건) -> 조건이 거짓이면 루프종료(처음부터 거짓이면 실행안함!)
contract While {
function while1(uint _n) public pure {
uint ab;
while(_n < ab) {
ab++;
}
}
uint[] public a;
function while_2(uint _n) public returns(uint[] memory) {
while(a.length <_n) {
a.push(a.length+1);
}
return a;
}
function while_3(uint _n) public pure returns(uint) {
uint _a;
while(_n > 10**_a) {
_a++;
}
return _a;
}
}
paper.status = paperStatus.voting; 이거 왜 오류냐냐
paperList[_title].status = paperStatus.voting; 이건 왜 되냐
=> paper.status는 그냥 구조체 가르키는 거고 paperList[_title].status는 key값을 통해 어떤 특정한 구조체를 가르키니까 당연하지.. mapping 다시 공부하자 ..