Description:
Smart contract deployed on Ethereum.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
// ____ ___ ___ ____ __ __
// /\ _`\ /\_ \ /'___\/\ _`\ /\ \__ __/\ \__
// \ \,\L\_\ __\//\ \ /\ \__/\ \ \L\ \___ _ __\ \ ,_\ _ __ __ /\_\ \ ,_\
// \/_\__ \ /'__`\ \ \ \ \ ,__\ \ ,__/ __`\/'__\ \ \/ /'__\/'__`\ \/\ \ \ \/
// /\ \L\ \/\ __/ \_\ \_\ \ \_/ \ \ \/\ \L\ \ \ \/ \ \ \_\ \ \//\ \L\.\_\ \ \ \ \_
// \ `\____\ \____\/\____\ \_\ \ \_\ \____/\ \_\ \ \__\ \_\ \__/.\_\ \_\ \__\
// \/_____/\/____/\/____/ \/_/ \/_/\/___/ \/_/ \/__/ \/_/ \/__/\/_/ \/_/\/__/
//
// SPDX-License-Identifier: MIT
// Copyright Han, 2025
pragma solidity ^0.8.25;
contract SelfPortrait {
event ArtpieceCreated(address indexed creator);
event ArtpieceTransferred(address indexed oldOwner, address indexed newOwner);
event BidAccepted(uint256 value, address indexed fromAddress, address indexed toAddress);
event BidPlaced(uint256 value, address indexed fromAddress);
event BidWithdrawn(uint256 value, address indexed fromAddress);
event ListedForSale(uint256 value, address indexed fromAddress, address indexed toAddress);
event SaleCanceled(uint256 value, address indexed fromAddress, address indexed toAddress);
event SaleCompleted(uint256 value, address indexed fromAddress, address indexed toAddress);
error FundsTransfer();
error InsufficientFunds();
error ListedForSaleToSpecificAddress();
error NoBid();
error NotForSale();
error NotOwner();
error NotRoyaltyRecipient();
error NotYourBid();
error NullAddress();
error RoyaltyTooHigh();
string public constant MANIFEST = (
'Untitled.' '
'
);
string public constant CORE = (
'"use strict";const credits="iq intersect and hash noise, Dave_Hoskins hash";let s={signature:"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjE2IiBoZWlnaHQ9IjIxNiIgdmlld0JveD0iMCAwIDIxNiAyMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOCA4SDIwOFYyMDhIOFY4Wk0wIDIxNlYwSDIxNlYyMTZIMFpNOTkgMTE3SDExN1Y5OUg5OVYxMTdaTTkzIDkzVjEyM0gxMjNWOTNIOTNaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K",mouse_sensitivity:1,mouse_limit:0,color_offset_frames:60,frame:0,res:[0,0],save_frames:0,base64Image:"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"},h={newline:String.fromCharCode(10),parser:new URL(window.location)};const mobile=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);let w=window,d=document,b=d.body;d.body.style.touchAction="none",d.body.style.userSelect="none";let c=d.createElement("canvas");c.style.display="block",b.appendChild(c);const image=d.createElement("img");image.src=s.signature.trim(),image.style.cssText="width:40px;z-index:50;position:fixed;bottom:20px;right:20px;",b.appendChild(image);const glOptions={powerPreference:"high-performance"};mobile&&delete glOptions.powerPreference,w.gl=c.getContext("webgl2",glOptions),h.uniform1i=(e,t)=>h.uniform(e,t,"uniform1i"),h.uniform=(e,t,r)=>{s.uniforms||={};(s.uniforms[e]||=(()=>{const o=gl.getUniformLocation(s.current_program,e),i=r||(Array.isArray(t)?"uniform2fv":"uniform1f");return{update:e=>gl[i](o,e)}})()).update(t)},h.resize=()=>{let e,t,r,o=h.ix.mouse.x/s.res[0],i=h.ix.mouse.y/s.res[1];const a=h.parser.searchParams.get("res",t);a?(e=t=a,r=1):(e=w.innerWidth,t=w.innerHeight,s.aspect&&(e>t*s.aspect?e=t*s.aspect:t=e/s.aspect),r=w.devicePixelRatio),s.res[0]=c.width=e*r,s.res[1]=c.height=t*r,c.style.width=e+"px",c.style.height=t+"px",h.ix.set(c.width*o,c.height*i)},h.ix={start:{x:0,y:0},mouse:{x:0,y:0}},h.ix.set=(e,t)=>{h.ix.mouse={x:e,y:t}},h.ix.start=e=>{h.ix.start.x=e.clientX,h.ix.start.y=e.clientY,d.addEventListener("pointermove",h.ix.move)},h.clamp=(e,t,r)=>Math.max(t,Math.min(r,e)),h.ix.move=e=>{h.ix.mouse.x+=(e.clientX-h.ix.start.x)*window.devicePixelRatio*s.mouse_sensitivity,h.ix.mouse.y-=(e.clientY-h.ix.start.y)*window.devicePixelRatio*s.mouse_sensitivity,h.ix.start.x=e.clientX,h.ix.start.y=e.clientY,h.ix.mouse.x=h.clamp(h.ix.mouse.x,s.res[0]*s.mouse_limit,s.res[0]*(1-s.mouse_limit)),h.ix.mouse.y=h.clamp(h.ix.mouse.y,s.res[1]*s.mouse_limit,s.res[1]*(1-s.mouse_limit))},h.ix.stop=e=>{d.removeEventListener("pointermove",h.ix.move)},h.save={},h.save.toImage=()=>{const e=new Date;let t=String(e.getFullYear()).slice(2,4)+"-"+e.getMonth()+"-"+e.getDate()+" ("+s.frame+").png",r=document.createElement("a");r.setAttribute("download",t);let o=c.toDataURL("image/png").replace("data:image/png","data:application/octet-stream");r.setAttribute("href",o),r.click(),r.remove()},h.loadTextureBase64=async e=>{e="data:image/jpg;base64,"+e;const t=new Image;t.crossOrigin="",t.src=e,await t.decode();const r=gl.createTexture();return gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,!0),gl.bindTexture(gl.TEXTURE_2D,r),gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE,t),gl.generateMipmap(gl.TEXTURE_2D),r},h.buildShader=(e,t)=>{let r=gl.createShader(e);return gl.shaderSource(r,t),gl.compileShader(r),r},h.initProgram=(e,t,r)=>{const o=gl.createProgram(),i=h.buildShader(gl.VERTEX_SHADER,t),a=h.buildShader(gl.FRAGMENT_SHADER,e);gl.attachShader(o,i),gl.attachShader(o,a),gl.linkProgram(o),gl.getShaderParameter(i,gl.COMPILE_STATUS)||console.error("V: "+gl.getShaderInfoLog(i)),gl.getShaderParameter(a,gl.COMPILE_STATUS)||console.error("F: "+gl.getShaderInfoLog(a)),gl.getProgramParameter(o,gl.LINK_STATUS)||console.error("P: "+gl.getProgramInfoLog(o));let n=gl.createBuffer(),s=gl.getAttribLocation(o,"p");return gl.bindBuffer(gl.ARRAY_BUFFER,n),gl.bufferData(gl.ARRAY_BUFFER,r,gl.STATIC_DRAW),gl.enableVertexAttribArray(s),gl.vertexAttribPointer(s,2,gl.FLOAT,!1,0,0),o},s.pixel=new Uint8Array(4),h.render=()=>{gl.viewport(0,0,c.width,c.height),gl.useProgram(s.program),s.current_program=s.program,h.uniform("u_time",.001*performance.now()),h.uniform("u_resolution",s.res),h.uniform("u_mouse",[h.ix.mouse.x,h.ix.mouse.y]),""!=s.texture0&&(gl.activeTexture(gl.TEXTURE0),gl.bindTexture(gl.TEXTURE_2D,s.texture0),h.uniform1i("u_texture_0",0)),gl.drawArrays(gl.TRIANGLE_STRIP,0,4),gl.readPixels(0,0,1,1,gl.RGBA,gl.UNSIGNED_BYTE,s.pixel),(h.save.queued||s.frame<s.save_frames&&s.frame>3)&&(h.save.queued=!1,h.save.toImage()),s.frame++,requestAnimationFrame(h.render)};const init=async()=>{if(gl){s.texture0=await h.loadTextureBase64(s.base64Image),h.resize(),h.ix.set(c.width/2,c.height/2),d.addEventListener("pointerdown",h.ix.start),d.addEventListener("pointerup",h.ix.stop),w.addEventListener("resize",h.resize),s.save_frames=h.parser.searchParams.get("frames")||0,d.addEventListener("keyup",e=>{if(!(e.ctrlKey||e.altKey||e.shiftKey||e.metaKey))switch(e.key){case"f":const e=prompt("Frames to render",s.save_frames);h.parser.searchParams.set("frames",e),window.location=h.parser.href;break;case"r":const t=prompt("Canvas size in pixels (max 8192)",c.height);t>=8&&t<=8192&&(h.parser.searchParams.set("res",t),window.location=h.parser.href);break;case"s":h.save.queued=!0}});let e=Float32Array.of(-1,1,-1,-1,1,1,1,-1);const t="#version 300 es"+h.newline+"precision highp float; in vec2 p; void main(){ gl_Position =vec4(p,1.0,1.0); }";let r="#version 300 es"+h.newline+"#ifdef GL_ES"+h.newline+"precision highp float;"+h.newline+"#endif"+h.newline+"const int AA=2;uniform vec2 u_resolution;uniform float u_time;uniform vec2 u_mouse;uniform sampler2D u_texture_0;uniform float u_chroma_offset;const vec3 f=vec3(.941176470588235),v=vec3(.901960784313726),m=vec3(.980392156862745),n=vec3(.5,3,3);float y;uniform bool u_animate_grid;"+h.newline+"#define R(a)mat2(cos(a),sin(a),-sin(a),cos(a))"+h.newline+"#define TAU 6.283185307"+h.newline+"#define PI 3.14159"+h.newline+"#define RANDOMS 32"+h.newline+"vec3 u=vec3(0);float r=1.f,T=0.f,c=0.f;vec2 a=vec2(0);vec4 i[RANDOMS];vec2 x=vec2(0);out vec4 fragColor;vec3 t(){vec3 f=gl_FragCoord.xyy,v;f=vec3(dot(f,vec3(127.1f,311.7f,74.7f)),dot(f,vec3(269.5f,183.3f,246.1f)),dot(f,vec3(113.5f,271.9f,124.6f)));v=-1.f+2.f*fract(sin(f)*43758.5453123f);return fract(555.f*sin(777.f*v))/256.f;}vec2 t(vec2 f){vec3 v=fract(vec3(f.xyx)*vec3(.1031,.103,.0973));v+=dot(v,v.yzx+33.33);return fract((v.xx+v.yz)*v.zy);}mat3 s(float f){float v=cos(f),m=sin(f);return mat3(1.,0.,0.,0.,v,-m,0.,m,v);}mat3 e(float f){float v=cos(f),m=sin(f);return mat3(v,0.,m,0.,1.,0.,-m,0.,v);}mat3 A(float f){float v=cos(f),m=sin(f);return mat3(v,-m,0.,m,v,0.,0.,0.,1.);}void A(out mat3 f,out float v,out float r){v=c;int m=int(t(a)*1e2),d=m%RANDOMS;vec4 n=i[d];vec2 y=n.xy,o=vec2(u.x*TAU);o.x*=max(y.x*3.,.5);o.y*=max(y.y*3.,.5);float x=y.x*TAU+o.x,z=y.y*TAU+o.y,T=u.x*TAU+n.z*TAU;f=e(T)*s(z)*A(x);r=1.;}bool A(vec3 f,vec3 v,vec3 m,out float r,out vec3 u){vec3 T=1./v,d=(-m-f)*T,y=(m-f)*T,n=min(d,y),o=max(d,y);float x=max(max(n.x,n.y),n.z),a=min(min(o.x,o.y),o.z);if(a<0.||x>a)return false;r=max(x,0.);u=x==n.x?vec3(-sign(v.x),0,0):x==n.y?vec3(0,-sign(v.y),0):vec3(0,0,-sign(v.z));return true;}float e(vec3 f,vec3 v,vec3 m){vec3 y=n;y+=vec3(sin(u.y*TAU),cos(u.y*TAU),0)*10.;y=normalize(f-y);float x=max(dot(v,y),0.f),d=max(dot(reflect(-y,v),-m),0.f),r=x*2.;r+=pow(max(1.f+dot(m,v),0.f),2.)*2.;r+=pow(d,1.)*1e-5;return r;}vec4 A(vec2 u,float y){vec3 x=m,n=vec3(0,0,-10.f+.001*T*r),d=normalize(vec3(0)-n),z=normalize(vec3(d.z,0,-d.x)),o=normalize(u.x*z+u.y*cross(d,z)+d/.2),a,c,s;mat3 U;float i,S,t;A(U,i,S);a=U*n;c=U*o;bool G=A(a,c,vec3(i),t,s);if(G&&t<1e2f){vec3 P=n+o*t,B=normalize(transpose(U)*s);x=mix(v,f,e(P,B,o));}return vec4(x,1);}void s(float f,float v,float y){float x=TAU*y*0.,m=1.f,d,o;m=.5f+.5f*sin(TAU*u_time/16./2.+x);d=(f-.2*m*v)/16.;o=(f-.9*m*v)/16.;T=v;r=m;u=vec3(d,o,f/16.);}float d(vec3 f){f=fract(f*.3183099+.1);f*=17.;return fract(f.x*f.y*f.z*(f.x+f.y+f.z));}float p(vec3 f){vec3 v=floor(f),y=fract(f);y=y*y*(3.-2.*y);return mix(mix(mix(d(v+vec3(0)),d(v+vec3(1,0,0)),y.x),mix(d(v+vec3(0,1,0)),d(v+vec3(1,1,0)),y.x),y.y),mix(mix(d(v+vec3(0,0,1)),d(v+vec3(1,0,1)),y.x),mix(d(v+vec3(0,1,1)),d(v+vec3(1)),y.x),y.y),y.z);}void A(){x=u_mouse/u_resolution;vec2 v=x*2.;for(float f=0.;f<float(RANDOMS);f++){float m=floor(f/20.),y=mod(f,20.);vec2 d=vec2(m,y);vec4 u=vec4(1);u.xy=t(d)*2.;u.z=p(vec3(d.x+v.x,d.y+v.y,2));i[int(f)]=u;}}void main(){y=u_animate_grid?(y=floor(fract(u_time/16.)*20./2.)*2.,max(y,1.)):20.;A();vec4 f=vec4(0,0,0,1),v;vec2 d=gl_FragCoord.xy;float x=.5f+.5f*sin(d.x*147.f)*sin(d.y*131.f);v=vec4(0,0,0,1);for(int r=0;r<AA;r++)for(int z=0;z<AA;z++){vec2 o=vec2(z,r)/float(AA)-.5f,n=(gl_FragCoord.xy+o-.5f*u_resolution.xy)/min(u_resolution.x,u_resolution.y),T=vec2(y),U=mod(T,2.f),i=vec2(0);float S=0.f;n*=1.f+.04;if(abs(n.x)<.5f&&abs(n.y)<.5f){vec2 G=(n+.5f*U)*T;n=fract(G)-.5f;a=floor(G)/T+.5f;n.y*=T.x/T.y;i=floor(G)+1.f;S=fract(sin(dot(i,vec2(12.9898f,78.233f)))*43758.5453f);float e=.5f*(1.f/2.)*(float(r*AA+z)+x)/float(AA*AA),P=u_time-e-S,B,b;s(P,0.f,S);v=texture(u_texture_0,floor(G)/T+.5f);B=(v.x+v.y+v.z)*.333f;b=mix(.95f,1.,.5f*cos(u.z*TAU)+.5f);B=smoothstep(1.,b,B);c=.2+B*.45;s(P,-1.f,S);f.x+=A(n,S).x;s(P,0.f,S);f.y+=A(n,S).y;s(P,1.f,S);f.z+=A(n,S).z;}else f+=vec4(m,1);}f/=float(AA*AA);f.xyz+=t();f.xyz=mix(f.xyz,v.xyz,0.);fragColor=vec4(f.xyz,1);}";if(mobile){const e="const int AA = 2";r=r.replace(e,"const int AA=1")}window.program=s.program=h.initProgram(r,t,e),h.render()}else{const e=d.createElement("div");e.style.cssText="align-items:center;background:#969696;color:#fff;display:flex;font-family:monospace;font-size:20px;height:100vh;justify-content:center;left:0;position:fixed;top:0;width:100vw;",e.innerHTML="Your browser does not support WebGL.",b.append(e)}};init();'
);
modifier onlyOwner() {
if (owner != msg.sender) {
revert NotOwner();
}
_;
}
modifier onlyRoyaltyRecipient() {
if (royaltyRecipient != msg.sender) {
revert NotRoyaltyRecipient();
}
_;
}
struct Offer {
bool active;
uint256 value;
address toAddress;
}
struct Bid {
bool active;
uint256 value;
address fromAddress;
}
address public owner;
Offer public currentOffer;
Bid public currentBid;
address public royaltyRecipient;
uint256 public royaltyPercentage;
mapping (address => uint256) public pendingWithdrawals;
constructor(uint256 _royaltyPercentage) {
if (_royaltyPercentage >= 100) {
revert RoyaltyTooHigh();
}
owner = msg.sender;
royaltyRecipient = msg.sender;
royaltyPercentage = _royaltyPercentage;
emit ArtpieceCreated(msg.sender);
}
function name() public view virtual returns (string memory) {
return 'SelfPortrait';
}
function symbol() public view virtual returns (string memory) {
return 'HAN';
}
function artpiece() public view virtual returns (string memory) {
return string.concat(
'<!DOCTYPE html>'
'<html>'
'<head>'
'<title>', 'SelfPortrait', '</title>'
'<meta name="viewport" content="width=device-width, initial-scale=1" />'
'<style>html,body{background:#969696;margin:0;padding:0;overflow:hidden;}</style>'
'</head>'
'<body>'
'<script type="text/javascript">',
CORE,
'</script>'
'</body>'
'</html>'
);
}
function withdraw() public {
uint256 amount = pendingWithdrawals[msg.sender];
pendingWithdrawals[msg.sender] = 0;
_sendFunds(amount);
}
function transferOwnership(address newOwner) public onlyOwner {
if (newOwner == address(0)) {
revert NullAddress();
}
_transferOwnership(newOwner);
if (currentBid.fromAddress == newOwner) {
uint256 amount = currentBid.value;
currentBid = Bid({ active: false, value: 0, fromAddress: address(0) });
pendingWithdrawals[newOwner] += amount;
}
if (currentOffer.active) {
currentOffer = Offer({ active: false, value: 0, toAddress: address(0) });
}
}
function listForSale(uint256 salePriceInWei) public onlyOwner {
currentOffer = Offer({ active: true, value: salePriceInWei, toAddress: address(0) });
emit ListedForSale(salePriceInWei, msg.sender, address(0));
}
function listForSaleToAddress(uint256 salePriceInWei, address toAddress) public onlyOwner {
currentOffer = Offer({ active: true, value: salePriceInWei, toAddress: toAddress });
emit ListedForSale(salePriceInWei, msg.sender, toAddress);
}
function cancelFromSale() public onlyOwner {
Offer memory oldOffer = currentOffer;
currentOffer = Offer({ active: false, value: 0, toAddress: address(0) });
emit SaleCanceled(oldOffer.value, msg.sender, oldOffer.toAddress);
}
function buyNow() public payable {
if (!currentOffer.active) {
revert NotForSale();
}
if (currentOffer.toAddress != address(0) && currentOffer.toAddress != msg.sender) {
revert ListedForSaleToSpecificAddress();
}
if (msg.value != currentOffer.value) {
revert InsufficientFunds();
}
currentOffer = Offer({ active: false, value: 0, toAddress: address(0) });
uint256 royaltyAmount = _calcRoyalty(msg.value);
pendingWithdrawals[owner] += msg.value - royaltyAmount;
pendingWithdrawals[royaltyRecipient] += royaltyAmount;
emit SaleCompleted(msg.value, owner, msg.sender);
_transferOwnership(msg.sender);
}
function placeBid() public payable {
if (msg.value <= currentBid.value) {
revert InsufficientFunds();
}
if (currentBid.value > 0) {
pendingWithdrawals[currentBid.fromAddress] += currentBid.value;
}
currentBid = Bid({ active: true, value: msg.value, fromAddress: msg.sender });
emit BidPlaced(msg.value, msg.sender);
}
function acceptBid() public onlyOwner {
if (!currentBid.active) {
revert NoBid();
}
uint256 amount = currentBid.value;
address bidder = currentBid.fromAddress;
currentOffer = Offer({ active: false, value: 0, toAddress: address(0) });
currentBid = Bid({ active: false, value: 0, fromAddress: address(0) });
uint256 royaltyAmount = _calcRoyalty(amount);
pendingWithdrawals[owner] += amount - royaltyAmount;
pendingWithdrawals[royaltyRecipient] += royaltyAmount;
emit BidAccepted(amount, owner, bidder);
_transferOwnership(bidder);
}
function withdrawBid() public {
if (msg.sender != currentBid.fromAddress) {
revert NotYourBid();
}
uint256 amount = currentBid.value;
currentBid = Bid({ active: false, value: 0, fromAddress: address(0) });
_sendFunds(amount);
emit BidWithdrawn(amount, msg.sender);
}
function setRoyaltyRecipient(address newRoyaltyRecipient) public onlyRoyaltyRecipient {
if (newRoyaltyRecipient == address(0)) {
revert NullAddress();
}
royaltyRecipient = newRoyaltyRecipient;
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = owner;
owner = newOwner;
emit ArtpieceTransferred(oldOwner, newOwner);
}
function _sendFunds(uint256 amount) internal virtual {
(bool success, ) = msg.sender.call{value: amount}('');
if (!success) {
revert FundsTransfer();
}
}
function _calcRoyalty(uint256 amount) internal virtual returns (uint256) {
return (amount * royaltyPercentage) / 100;
}
}
Submitted on: 2025-11-01 18:40:43
Comments
Log in to comment.
No comments yet.