Commit 853214ec authored by Kegan's avatar Kegan
Browse files

updated website. Started working on SteamToEther.sol Added notes files.

parent 976149cb
......@@ -9,9 +9,11 @@ contract SteamToEther is Context {
using Address for address;
mapping(uint64 => address[]) internal steamIdToEther;
mapping(address => uint64) internal etherToSteamID;
mapping(uint64 => address[]) internal steamIdToEther;
mapping(address => uint64) internal etherToSteamID;
event AccountLinked(address _wallet, uint64 _steamId64);
event AccountUnlinked(address _wallet, uint64 _steamId64);
constructor() {
console.log("Deployed SteamToEtherContract!");
......@@ -30,7 +32,11 @@ contract SteamToEther is Context {
return steamIdToEther[_steamId];
}
event AccountLinked(address _wallet, uint64 _steamId64);
function UnleakSteamAccount(uint64 _steamId64) public {
//TODO: unlink the provided steam account from our sender
}
function LinkSteamAccount(uint64 _steamId64) public {
address sender = _msgSender();
......
/*
Web 3.0 implementation for DayZ Standalone
in this file, you'll find all the user-facing structures for Web3 interaction.
I was heavily inspired by the Ethers.js implementation
Creator: Kegan 'Lystic' Hollern
Last Modified: Sept 6th 2021
Note: This library makes use of the JSON-RPC interface published by Infura
*/
const string WEB3_VERSION = "0.1.0";
class Provider {
void Provider(string network_endpoint)
{
}
T Send<T>(string method, ref Params args)
{
return null;
}
}
// TODO: figure out how to implement signers (wallets) in DayZ in a semi-secure fashion.
class Signer {
}
void WEB3_TEST()
{
ref Provider jsonRpcProvider = new Provider("https://infura.io/v3/key");
ref Array<string> accounts = jsonRpcProvider.Send<ref Array<string>>("eth_requestAccounts",null);
}
\ No newline at end of file
DayZ Mods
===
Above is the source code for the mods built as part of SkinZ
\ No newline at end of file
.obsidian/
\ No newline at end of file
# Create JSON_RPC Mod for DayZ
We need a way to interact with the blockchain in a decentralized way. So we should directly send JSON_RPC requests from DayZ.
See [[Modding]] for info on Modding DayZ
## Initial Version
The goal of the initial version is to enable smart contract calling functionality without a signer. This should allow us to interact with "view" or "pure" methods on the blockchain.
See [[Solidity]] for info on view and pure methods.
# Skin-Z DayZ Mod
Requires [[DayZ JSON_RPC Mod]] be completed first!
\ No newline at end of file
# SteamToEth.sol
This is a smart contract for storing SteamID<->ETH mappings on the blockchain.
*Note: SteamID ownership is not verified*
*Note: No anonymity possible in this state*
#### Anonyminity?
We could do an anonymous version of this with something like:
- `LinkAccount ( HASH_OF_STEAMID64 )`
- `VerifyOwnership ( HASH_OF_STEAMID64, ETH_WALLET ) returns ( bool )`
##### does this work?
Maybe? Could someone simply hash the targets steam id and look for the ETH wallet ? yes, but not if we also hash that ETH wallet
Proposed expansion:
- In VerifyOwnership we do `HASH( ETH_WALLET )`
- When storing, we store `mapping(HASH_OF_STEAMID64 => HASH_OF_ETH_WALLET)`
Under this solution, without previously knowing the ETH wallet and STEAMID64, we cannot get the ETH wallet of a steamID.
What about bruteforcing the ETH wallet? Not feasable.
##### end user perspective
The problem here is that the only way to determine the NFTs owned by a player is to also know what ETH wallet they have. The end user could tell us what their ETH wallet is, but that adds a layer of user-interaction.
# Modding for DayZ
## Available Resources
- [[Mod Structure]]
- [[EnScript]]
- [[Workbench]]
\ No newline at end of file
# EnScript notes
\ No newline at end of file
# Workbench app notes
\ No newline at end of file
# Arbitrum notes
Arbitrum is an optimistic rollup for ETH. It has nearly full EVM support but has some key differences we'll need to take note of.
\ No newline at end of file
# Hardhat development
Hardhat is a newer development environment for the EVM. I think it's a significant improvement over REMIX development and way easier than TRUFFLE.
## Notable functions
`npx hardhat compile` -> Compiles our smart contracts
`npx hardhat test` -> Runs our test files
`npx hardhat run .\script.js` -> Run a JS file w/ hardhat
# Solidity smart contract notes
Solidity is the prefered language to write smart contracts in. See [[Hardhat]] for a development environment.
## View vs Pure
the `VIEW` keyword is for functions that read, but do not modify the state of the blockchian.
the `PURE` keybword is for functions that neither read nor modify the blockchain.
# SteamID To ETH wallet
We need a smart way to translate a player's Steam ID into an ETH wallet.
### Do we need to verify that a steam id is owned by the wallet owner?
Not really. Think of it this way, if you lie about what steam account is yours, then the NFTs associated with your wallet just go to someone else.
## Plan
Create a smart contract that stores SteamID->ETH and ETH->SteamID translations
#### But wait!
We need SteamID->ETH(array) because I could own multiple ETH wallets
Smart contract notes here: [[SteamToEth.sol]]
\ No newline at end of file
......@@ -134,6 +134,7 @@ blockquote {
font-size: 16px;
line-height: 20px;
font-weight: 500;
text-align: center;
}
.text-underline {
......@@ -655,6 +656,10 @@ blockquote {
transform: translate(0px, 0px);
}
.cloneable-container-default.account-link-container {
min-height: 300px;
}
.grid-2-columns {
grid-column-gap: 32px;
-ms-grid-rows: auto;
......@@ -1006,6 +1011,15 @@ blockquote {
}
.accordion-item-title---brix {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
min-height: 50px;
-webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
color: #170f49;
font-size: 22px;
line-height: 28px;
......@@ -1330,7 +1344,42 @@ blockquote {
font-size: 18px;
}
.paragraph-3 {
text-align: center;
}
.success-message-2 {
border: 2px solid transparent;
border-radius: 14px;
background-color: #f7f7fb;
}
.grid {
margin-top: 18px;
grid-row-gap: 3px;
-ms-grid-columns: 1fr;
grid-template-columns: 1fr;
-ms-grid-rows: auto 1fr;
grid-template-rows: auto 1fr;
}
.grid-2 {
-ms-grid-columns: 0.75fr 0.25fr;
grid-template-columns: 0.75fr 0.25fr;
-ms-grid-rows: auto;
grid-template-rows: auto;
}
.text-block-2 {
margin-left: 10px;
text-align: left;
}
@media screen and (min-width: 1440px) {
.text-uppercase.subtitle {
text-align: center;
}
.notification-header {
position: static;
}
......@@ -1338,6 +1387,10 @@ blockquote {
.section-2 {
height: 35px;
}
.paragraph-3 {
text-align: center;
}
}
@media screen and (min-width: 1920px) {
......@@ -1382,6 +1435,29 @@ blockquote {
color: #615e83;
font-size: 16px;
}
.accordion-item-title---brix {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
min-height: 50px;
-webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
}
.grid {
grid-auto-columns: 1fr;
grid-row-gap: 3px;
-ms-grid-rows: auto 1fr;
grid-template-rows: auto 1fr;
}
.text-block-2 {
margin-left: 10px;
}
}
@media screen and (max-width: 991px) {
......@@ -1870,6 +1946,14 @@ blockquote {
.paragraph-2 {
white-space: normal;
}
.grid {
margin-top: 18px;
}
.text-block-2 {
text-align: right;
}
}
#w-node-c054886d-07d1-a130-b374-a7e8d59be279-d59be275 {
......
<!DOCTYPE html><!-- This site was created in Webflow. http://www.webflow.com -->
<!-- Last Published: Mon Sep 06 2021 01:55:17 GMT+0000 (Coordinated Universal Time) -->
<!-- Last Published: Mon Sep 06 2021 14:31:08 GMT+0000 (Coordinated Universal Time) -->
<html data-wf-page="6134d5b7d6b22ccf9fd8df81" data-wf-site="6134d5b6d6b22c5832d8df7c">
<head>
<meta charset="utf-8">
......@@ -31,7 +31,7 @@
</head>
<body>
<div class="page-wrapper">
<div id="header-error-notification" style="display: none !important;" class="section-2 wf-section">
<div id="header-error-notification" style="display: none !important" class="section-2 wf-section">
<div class="notification-header">
<p id="header-error-text" class="paragraph-2">You are not connected to the Arbitrum Network!</p>
</div>
......@@ -63,6 +63,47 @@
</div>
</div>
</div>
<div class="section cloneables-listing wf-section">
<div class="container-default w-container">
<div data-w-id="c054886d-07d1-a130-b374-a7e8d59be275" class="cloneable-header">
<div class="w-layout-grid cloneable-header-grid">
<h2 class="heading-size-3">Link your Steam Account to Skin-Z</h2>
<a href="#" id="w-node-c054886d-07d1-a130-b374-a7e8d59be279-d59be275" target="_blank" class="button-secondary cloneable-header-button w-button">Why is this Necessary?</a>
</div>
</div>
<div class="cloneable-container-default account-link-container">
<div class="accordion-item-wrapper---brix">
<div class="accordion-item---brix accordion-1---brix">
<div class="text-uppercase subtitle">Link your steam account</div>
<div class="form-newsletter w-form">
<form id="wf-form-SteamID-Form" name="wf-form-SteamID-Form" data-name="SteamID-Form" method="get" action="#" class="form-newsletter-wrapper"><input type="number" class="input-relative newsletter footer w-input" maxlength="256" name="SteamID64" data-name="SteamID64" placeholder="SteamID64 Ex: &#x27;12345671234567890&#x27;" id="SteamID" required=""><input type="submit" value="Link Steam ID" data-wait="Please wait..." class="button-primary newsletter button-footer w-button"></form>
<div class="success-message-2 w-form-done">
<div class="text-uppercase subtitle">Steam Account linked successfully</div>
</div>
<div class="error-message newsletter w-form-fail">
<div>Uh oh! Failed to link steam account.</div>
</div>
</div>
</div>
</div>
<div class="accordion-item-wrapper---brix">
<div class="accordion-item---brix accordion-1---brix">
<div class="accordion-item-title---brix">Linked Steam Accounts</div>
<div class="w-layout-grid grid">
<div class="text-block-2">12345671234567890 <a href="#">unlink</a>
</div>
<div class="text-block-2">12345671234567890 <a href="#">unlink</a>
</div>
<div class="text-block-2">12345671234567890 <a href="#">unlink</a>
</div>
<div class="text-block-2">12345671234567890 <a href="#">unlink</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="section cloneables-listing wf-section">
<div class="container-default w-container">
<div data-w-id="c054886d-07d1-a130-b374-a7e8d59be275" class="cloneable-header">
......@@ -494,167 +535,6 @@
<!-- [if lte IE 9]><script src="https://cdnjs.cloudflare.com/ajax/libs/placeholders/3.0.2/placeholders.min.js"></script><![endif] -->
<script type="module">
import { ethers } from "./js/ethers.js";
import infura from "./js/infura.js";
const error_banner = document.getElementById('header-error-notification');
const error_text = document.getElementById('header-error-text');
const connect_txt = document.getElementById('connect-wallet-btn-text');
const connect_btn = document.getElementById('connect-wallet-btn');
const is_web3 = (window.ethereum != undefined);
const provider = !is_web3 ? new ethers.providers.JsonRpcProvider(infura.getNetwork()) : new ethers.providers.Web3Provider(window.ethereum);
var signer = null;
const IsWalletConnected = async () => {
return (await provider.listAccounts()).length > 0;
};
const OnConnectClicked = async () => {
// 1. determine if we can connect a wallet?
if(!is_web3) return; // infura -> do nothing
if(await IsWalletConnected()) return; // wallet already connected
try {
await provider.send("eth_requestAccounts", []); //temp link metamask
} catch (e) {
console.log(e);
return; //connection rejected?!
}
OnWalletLinked();
};
const OnWalletLinked = async () => {
signer = provider.getSigner();
connect_btn.classList.add("button-secondary");
//display address or ENS name
let address = await signer.getAddress();
let ens = await GetENSName(address);
connect_txt.innerHTML = (ens == null ? await signer.getAddress() : ens);
}
const GetABI = async () => {
if(!IsOnArbitrum()) return [];
let network = await provider.getNetwork();
if(network.chainId == 421611)
{
return [
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "_wallet",
"type": "address"
},
{
"indexed": false,
"internalType": "uint64",
"name": "_steamId64",
"type": "uint64"
}
],
"name": "AccountLinked",
"type": "event"
},
{
"inputs": [
{
"internalType": "uint64",
"name": "_steamId",
"type": "uint64"
}
],
"name": "GetEthereumWallets",
"outputs": [
{
"internalType": "address[]",
"name": "",
"type": "address[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_addr",
"type": "address"
}
],
"name": "GetSteamAccount",
"outputs": [
{
"internalType": "uint64",
"name": "",
"type": "uint64"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint64",
"name": "_steamId64",
"type": "uint64"
}
],
"name": "LinkSteamAccount",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
];
}
if(network.chainId == 42161)
{
return []; //current mainnet contract abi
}
return [];
};
const IsOnArbitrum = async () => {
let network = await provider.getNetwork();
if(network.chainId == 421611 || network.chainId == 42161)
return true;
return false;
};
const GetENSName = (address) => {
let temp_provider = new ethers.providers.JsonRpcProvider(infura.getEthMainnet());
return temp_provider.lookupAddress(address);
};
const HideErrorBanner = () => {
error_banner.style.display = "none !important";
};
const ShowErrorBanner = (text) => {
error_text.innerHTML = text;
error_banner.style.display = "block";
};
if(await IsWalletConnected()) OnWalletLinked();
connect_btn.onclick = OnConnectClicked; //on btn click call onConnectClicked
if(!await IsOnArbitrum())
{
ShowErrorBanner("You are not connected to the <a href=\"https://arbitrum.io/\" target=\"_blank\">Arbitrum</a> Network!");
}
</script>
<script src="js/main.js" type="module"></script>
</body>
</html>
\ No newline at end of file
import { ethers } from "./ethers.js";
import infura from "./infura.js";
const error_banner = document.getElementById('header-error-notification');
const error_text = document.getElementById('header-error-text');
const connect_txt = document.getElementById('connect-wallet-btn-text');
const connect_btn = document.getElementById('connect-wallet-btn');
const is_web3 = (window.ethereum != undefined);
const provider = !is_web3 ? new ethers.providers.JsonRpcProvider(infura.getNetwork()) : new ethers.providers.Web3Provider(window.ethereum);
var signer = null;
const IsWalletConnected = async () => {
return (await provider.listAccounts()).length > 0;
};
const OnConnectClicked = async () => {
// 1. determine if we can connect a wallet?
if(!is_web3) return; // infura -> do nothing
if(await IsWalletConnected()) return; // wallet already connected
try {
await provider.send("eth_requestAccounts", []); //temp link metamask
} catch (e) {
console.log(e);
return; //connection rejected?!
}
OnWalletLinked();
};
const OnWalletLinked = async () => {
signer = provider.getSigner();
connect_btn.classList.add("button-secondary");
//display address or ENS name
let address = await signer.getAddress();
let ens = await GetENSName(address);
connect_txt.innerHTML = (ens == null ? await signer.getAddress() : ens);
}
const GetABI = async () => {
if(!IsOnArbitrum()) return [];
let network = await provider.getNetwork();
if(network.chainId == 421611)
{
return [
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{