[TIL] 2023-05-30 DAY49
GIT 주소 : https://github.com/dowoo303/SOLIDITY
오늘 배운것들
- TEST10 시작
- TEST8 리뷰
1) 코드 리뷰
2) bytes형 비교 및 uint변환- ERC1155
- 비트코인 백서읽기
각종 팁
- 프론트에서 solidity로 넘겨줄 때 자료를 쉽게 넘겨줄 수 있는 방법이 있다면 전처리 후 넘겨주면되기 때문에 solidity에서 모든 작업을 생각하는 것이 아닌전체적인 맥락에서 생각할 필요가 있다. 예를 들면 숫자형과 문자형을 섞어서 받는 경우 프론트에서 받아서 js에서 toString을 해준 후 solidity에 넘겨주면 solidity에서 할일이 많이 줄어든다.
-> 요약: 한 섹터에서 모든 작업을 할 필요는 없다.- bytes1은 uint8이랑, bytes2는 uint16이랑 변환이 가능하다.
- string을 bytes1으로 바꾸는 두가지 방법: bytes1(string) = abi.encodePacked(string)[0]
-> 차이점: abi를 사용하면 다양한 자료형을 한번에 묶어서 bytes로 표현이 가능하다.- 백서
1) 비트코인의 아웃풋은 최대 2개다.(UTXO 중 일부인 1개는 상대방에게, 1개는 나에게)
2) 개인공개키 쌍을 이용하여 검증과 거래가 가능하기 때문에 전통거래에서는 불가능했던 모든 거래 공개가 가능해졌다.
회고
- 부산에서는 노트북으로 수업을 들으니까 좀 불편하네..
- 질문을 할 때는 그 사람의 위치나 상황을 파악해야할 뿐 아니라 질문이 명확해야한다. 예를 들면 그 사람의 인터뷰나 강연 등을 보고 내가 이해한 부분과 이해하지 못한 부분들을 정확히 이해하고 내가 이해하지 못한 궁금했던 점들을 묻는게 좋은 질문이다.(좋은 질문은 그 사람에게 좋은 인상을 남길 수 있다)
배열에서는 ==와 같은 비교가 불가능하다.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Q8 {
uint[] numbers = [1,2,3,4];
string[] letters = ["a", "b"];
// 로또 번호 입력, 맞추는기능 - 유저가 로또 번호를 입력하는 기능, 로또 번호를 맞추는 기능
function setLotto(uint[] calldata _numbers, string[] calldata _letters) public payable {
require(msg.value==0.05 ether);
uint fit = isSameNumber(_numbers) + isSameLetter(_letters);
getPrize(fit);
}
function getPrize(uint _n) private /*public으로 하면 자선사업가*/ {
if(_n==6) {
payable(msg.sender).transfer(1 ether);
} else if(_n==5) {
payable(msg.sender).transfer(0.75 ether);
} else if(_n==4) {
payable(msg.sender).transfer(0.25 ether);
} else if(_n==3) {
payable(msg.sender).transfer(0.1 ether);
}
}
// 숫자배열 비교하기 - 각 자리 for돌려서 count 세기기
function isSameNumber(uint[] calldata _myNumber) public view returns(uint) {
uint count;
for(uint i=0; i<numbers.length; i++) {
if(numbers[i]==_myNumber[i]) {
count++;
}
}
return count;
}
function isSameLetter(string[] calldata _myLetter) public view returns(uint) {
uint count;
for(uint i=0; i<letters.length; i++) {
if(letterCompare(letters[i], _myLetter[i])) {
count++;
}
}
return count;
}
// 문자배열 비교하기 - keccak256(abi.encodePacked(문자열)) 이용해서 비교 후 위와 같이 for돌려서 count 갱신
function letterCompare(string memory _a, string calldata _b) public pure returns(bool) {
return keccak256(abi.encodePacked(_a)) == keccak256(abi.encodePacked(_b));
}
}
contract Q8_2 {
string[] public letters;
address owner;
constructor() {
owner = msg.sender;
}
// 숫자랑 문자랑 섞여있으니까 차라리 숫자를 문자로 바꿔서 한번에 처리하는것이 좋음(solidity로 자료를 넘기기전에 js에서 처리 후 받았다고 가정)
function setTargetNumber(string[] memory _letters) public {
require(owner == msg.sender);
letters = _letters;
}
// 로또 번호 입력, 맞추는기능 - 유저가 로또 번호를 입력하는 기능, 로또 번호를 맞추는 기능
function setLotto(string[] calldata _letters) public payable {
require(msg.value==0.05 ether);
uint fit = isSameLetter(_letters);
getPrize(fit);
}
function getPrize(uint _n) private /*public으로 하면 자선사업가*/ {
if(_n==6) {
payable(msg.sender).transfer(1 ether);
} else if(_n==5) {
payable(msg.sender).transfer(0.75 ether);
} else if(_n==4) {
payable(msg.sender).transfer(0.25 ether);
} else if(_n==3) {
payable(msg.sender).transfer(0.1 ether);
}
}
function isSameLetter(string[] calldata _myLetter) public view returns(uint) {
uint count;
for(uint i=0; i<letters.length; i++) {
if(letterCompare(letters[i], _myLetter[i])) {
count++;
}
}
return count;
}
function letterCompare(string memory _a, string calldata _b) public pure returns(bool) {
return keccak256(abi.encodePacked(_a)) == keccak256(abi.encodePacked(_b));
}
}
// string을 input으로 받아서 bytes1배열로 변경 후 순서를 sorting해주고 중간값을 구하여 a라는 string배열에 넣는다.
contract Q8_3 {
// 로또 번호 설정 기능
string[6] targetLetters;
function setLotto(string[] memory _set1, string[] memory _set2, string[] memory _set3, string[] memory _set4, string[] memory _set5, string[] memory _set6) public {
targetLetters[0] = string(abi.encodePacked(getMedian_Number(stringArrayToBytes1Array(_set1))));
targetLetters[1] = string(abi.encodePacked(getMedian_Number(stringArrayToBytes1Array(_set2))));
targetLetters[2] = string(abi.encodePacked(getMedian_Number(stringArrayToBytes1Array(_set3))));
targetLetters[3] = string(abi.encodePacked(getMedian_Number(stringArrayToBytes1Array(_set4))));
targetLetters[4] = string(abi.encodePacked(getMedian_Number(stringArrayToBytes1Array(_set5))));
targetLetters[5] = string(abi.encodePacked(getMedian_Number(stringArrayToBytes1Array(_set6))));
}
function stringArrayToBytes1Array(string[] memory _a) public pure returns(bytes1[] memory) {
uint _n = _a.length;
bytes1[] memory _b = new bytes1[](_n);
for(uint i=0; i<_n;i++) {
_b[i] = abi.encodePacked(_a[i])[0];
}
return _b;
}
function bytesAverage(bytes1 a, bytes1 b) public pure returns(bytes1) {
return bytes1((uint8(a) + uint8(b))/2);
}
function getMedian_Number(bytes1[] memory numbers) public pure returns(bytes1){
uint _l = numbers.length;
for(uint i=0;i<_l-1;i++) {
for(uint j=i+1; j<_l ;j++) {
if(numbers[i] < numbers[j]) {
(numbers[i], numbers[j]) = (numbers[j], numbers[i]);
}
}
}
if(_l %2 ==0) {
return bytesAverage(numbers[_l/2-1], numbers[_l/2]);
} else {
return (numbers[_l/2]);
}
}
// 로또 번호 입력, 맞추는기능 - 유저가 로또 번호를 입력하는 기능, 로또 번호를 맞추는 기능
function setLotto(string[] calldata _letters) public payable {
require(msg.value==0.05 ether);
uint fit = isSameLetter(_letters);
getPrize(fit);
}
function getPrize(uint _n) private /*public으로 하면 자선사업가*/ {
if(_n==6) {
payable(msg.sender).transfer(1 ether);
} else if(_n==5) {
payable(msg.sender).transfer(0.75 ether);
} else if(_n==4) {
payable(msg.sender).transfer(0.25 ether);
} else if(_n==3) {
payable(msg.sender).transfer(0.1 ether);
}
}
function isSameLetter(string[] calldata _myLetter) public view returns(uint) {
uint count;
for(uint i=0; i<targetLetters.length; i++) {
if(letterCompare(targetLetters[i], _myLetter[i])) {
count++;
}
}
return count;
}
function letterCompare(string memory _a, string calldata _b) public pure returns(bool) {
return keccak256(abi.encodePacked(_a)) == keccak256(abi.encodePacked(_b));
}
}
contract BytesCompare {
bytes1 a = 0x12;
bytes1 b = 0x23;
function compare() public view returns(bool) {
return b>a;
}
function compare2(bytes1 _a, bytes1 _b) public pure returns(bool) {
return _b>_a;
}
// bytes1들끼리는 비교가 가능하다
// bytes는 동적이리서 비교 불가!
// function compare3(bytes memory _a, bytes memory _b) public pure returns(bool) {
// return _b>_a;
// }
// bytes1은 uint8로 변환가능능
function bytes1ToUint(bytes1 _a) public pure returns(uint8) {
return uint8(_a);
}
function uintToBytes1(uint8 _a) public pure returns(bytes1) {
return bytes1(_a);
}
function bytesAdd() public view returns(bytes1) {
return bytes1((uint8(a) + uint8(b))/2);
}
}
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
/*
시험시간: 30분
흔히들 비밀번호 만들 때 대소문자 숫자가 각각 1개씩은 포함되어 있어야 한다 등의 조건이 붙는 경우가 있습니다. 그러한 조건을 구현하세요.
입력값을 받으면 그 입력값 안에 대문자, 소문자 그리고 숫자가 최소한 1개씩은 포함되어 있는지 여부를 알려주는 함수를 구현하세요.
*/
contract TEST10 {
function bytestoBytesArray(bytes memory _bytes) public pure returns(bytes1[] memory) {
bytes1[] memory _bytes1 = new bytes1[](_bytes.length);
for(uint i=0; i<_bytes1.length; i++) {
_bytes1[i] = _bytes[i];
}
return _bytes1;
}
function passWord(string memory _a) public returns(bool) {
bool bigWord;
bool smallWord;
bool number;
bytes1[] memory a = new bytes1[](bytes(_a).length); // 길이만큼 자리 배정
a = bytestoBytesArray(bytes(_a));
for(uint i=0; i<a.length; i++) {
if(abi.encodePacked(a[i]) <= abi.encodePacked(a[i]) && abi.encodePacked(a[i])<= 90) {
bigWord = true;
}
if(97 <= abi.encodePacked(a[i]) && abi.encodePacked(a[i])<= 122) {
smallWord = true;
}
if(48 <= abi.encodePacked(a[i]) && abi.encodePacked(a[i])<= 57) {
number = true;
}
}
return (bigWord && smallWord && number);
}
}
ERC20, 721과 다르게 ERC1155는 코인을 1개만 관리하는 것이 아니라 여러개 관리가 가능하다.(그래서 _balances mapping이 이중mapping이다)
ERC20 - 코인 한개 관리
ERC721 - 멤버쉽
ERC1155 - 여러가지 코인 한번에 관리
거래를 일으켜주고 완성시켜주는 것은 노드